Source: https://docs.debitura.com/referral-partners/going-live-checklist

# Go live

You've validated your integration against the test environment. This page covers what needs to be in place before production traffic reaches Debitura, then one checklist per integration: [Starter](https://docs.debitura.com/referral-partners/going-live-checklist.md#starter-integration-checklist) and [Full](https://docs.debitura.com/referral-partners/going-live-checklist.md#full-integration-checklist).

**Business context:** See [How to go live (non-technical checklist)](https://support.debitura.com/en/articles/13913375-referral-partners-how-to-go-live-non-technical-checklist) for the commercial go-live steps your business and operations team needs to complete.

<a id="environments"></a>

## Environments

Debitura runs two fully isolated environments. Credentials, webhook subscriptions, clients, cases, tokens, and signing secrets are all environment-scoped — production and test never share data in either direction.

| Service | Production | Test | Used for |
| --- | --- | --- | --- |
| Referral Partner API | `referral-api.debitura.com` | `testreferral-api.debitura.com` | Client onboarding, token minting, webhooks, reporting |
| Customer API | `customer-api.debitura.com` | `testcustomer-api.debitura.com` | Case submission and management (Full Integration) |
| White-Label UI | `referral.debitura.com` | `testreferral.debitura.com` | Onboarding and signing URLs presented to clients |

Enforcement is identical across environments

KYC, SDCA, PoA, and zone requirements are driven by per-partner flags and per-jurisdiction configuration — not by which environment you're in. A flow that works in test will behave the same way in production, provided you test against a collection partner with the same enforcement profile as your production partner. Test with a KYC-required partner if your production cases will route to one.

<a id="production-readiness"></a>

## Production readiness

Three things need to be in place before your production build calls Debitura. How you deploy them — single environment with feature flags, separate staging/prod builds, blue-green cutover — is up to you.

<a id="1-request-production-credentials"></a>

### 1\. Request production credentials

Production API keys are issued by Debitura separately from test keys. Contact your Debitura account manager to request them. You will receive:

-   A production `XApiKey` for the Referral Partner API
-   Confirmation that your partner account is enabled in production

Keep the test key — you will still need it for regression testing and staging going forward.

<a id="2-point-production-at-the-production-hosts"></a>

### 2\. Point production at the production hosts

Make sure your production build is configured with the production API base URLs listed above: `referral-api.debitura.com`, plus `customer-api.debitura.com` if you use the Customer API. Common miss: hardcoded URLs in webhook-handling code, background jobs, or retry logic.

The White-Label UI host (`referral.debitura.com` vs `testreferral.debitura.com`) is **not** something you configure — it is returned inside `solutionUrl` values by the API you called. If your production build calls the production API, the signing URLs it receives will already point at the production UI.

<a id="3-register-webhook-subscriptions-in-production"></a>

### 3\. Register webhook subscriptions in production

Webhook subscriptions do not migrate between environments. Create new subscriptions in production via `POST /v1/webhooks` on `referral-api.debitura.com`.

-   **Save the signing secret** returned at creation time — it is never returned again and differs from your test secret
-   **Configure your production handler** to verify signatures using the production secret
-   **Subscribe to the same event types** you use in test. See [Which events you need](https://docs.debitura.com/referral-partners/integration-guides/webhooks.md#which-events-you-need) for each integration

See [Webhooks](https://docs.debitura.com/referral-partners/integration-guides/webhooks.md) for the full setup.

<a id="dry-run-your-first-production-case-with-istest-true"></a>

### Dry-run your first production case with `isTest: true`

Before opening the integration to real customer traffic, send a request to the production host with `isTest: true` to create classified test data. On Starter, set `isTest: true` on the invoice in `POST /collection-requests`; on Full, on the case. Test cases are excluded from production metrics, and automatic validation is not scheduled for Test/Demo cases. This does not guarantee that the full production workflow is exercised or that a collection partner can never receive the case.

```json
POST https://customer-api.debitura.com/cases
{
  "isTest": true,
  "currencyCode": "…",
  "amountToRecover": …,
  // rest of the case payload
}
```

Once the dry-run case completes and all your systems behave as expected, submit real cases with `isTest` unset (or `false`).

tip

Let your Debitura account manager know before you send the dry-run case so someone on Debitura's side can watch webhook delivery and case creation alongside you during your first production call.

<a id="starter-integration-checklist"></a>

## Starter Integration checklist

-   [ ]  **Production key and host**: `XApiKey` for production, requests to `referral-api.debitura.com`, from your server only
-   [ ]  **Branding and return destination** set on your partner account; verify the logo and colour via `GET /me`
-   [ ]  **One invoice per request**: multi-select sends one request per invoice
-   [ ]  **Stable identifiers**: `externalTenantId` per client and `creditorReference` per invoice, stored durably
-   [ ]  **Retries reuse the `Idempotency-Key`**, and you check the current request before resubmitting after a timeout or `5xx`
-   [ ]  **Request `id` stored** for every request, so your button can read the current state
-   [ ]  **Every `status` handled**: open `solutionUrl` for `awaiting_*`, `needs_fixing` and `submitted`; show "in progress" for `processing`; show the reason for `rejected` and `expired`, with no link. See [the status table](https://docs.debitura.com/referral-partners/integration-guides/starter-integration.md#2-open-the-next-action)
-   [ ]  **No URLs assembled by you**: only open the `solutionUrl` Debitura returns
-   [ ]  **Branch on the body's `status`**, not on `201`, `202` or `422` alone
-   [ ]  **`collection_request.updated` subscribed** in production, signatures verified, deliveries deduplicated; a missing event triggers a read, never a new request
-   [ ]  **`isTest` omitted or `false`** on real production invoices
-   [ ]  **Tested end to end in test**: a new client (onboarding), an existing client (approval), an invoice that needs fixing, and a debtor country that requires KYC

<a id="full-integration-checklist"></a>

## Full Integration checklist

Verify every integration requirement before switching to production.

<a id="prerequisites"></a>

### Prerequisites

-   [ ]  **Partnership agreement signed** and API credentials received for both test and production
-   [ ]  **White-label branding configured** — verify via `GET /me` that `logoUrl` and `backgroundColorCode` are correct
-   [ ]  **Production URLs configured** — not pointing at test environment

<a id="authentication"></a>

### Authentication

-   [ ]  **Bearer tokens** minted via `POST /oauth/token` per `externalTenantId`, cached per client, re-minted only on 401 — never hardcoded or shared across clients
-   [ ]  **Retry-on-401 pattern** implemented — re-mint once, treat second 401 as invalid client link. See [Token Expiry Handling](https://docs.debitura.com/referral-partners/getting-started/authentication.md#token-expiry-handling).

<a id="client-onboarding"></a>

### Client Onboarding

-   [ ]  **All `POST /clients` response codes handled**: `201`, `202`, the `409` types `ClientExistsNeedsLinking`, `ClientAlreadyLinkedToAnotherPartner`, `UserCreationFailed` and `PartnerNotAcceptingReferrals`, the `409` with `businessErrors[0].type: IdempotencyKeyInProgress` and `Retry-After: 2` when you send an `Idempotency-Key`, `400` for invalid fields or cases, and `422` for `AmountBelowMinimum` or `IdempotencyConflict`. See [Handling 409 Conflicts](https://docs.debitura.com/referral-partners/integration-guides/client-onboarding-conflicts.md).
-   [ ]  **Onboarding URL delivered to the client**: Debitura does not email it when you create the client. You must present the URL. Contract-signing reminders for waiting production cases are the only Debitura emails that link to it. See [White-Label UI](https://docs.debitura.com/referral-partners/concepts/white-label-ui.md).
-   [ ]  **Return URL appended** to onboarding and signing URLs, URL-encoded if it contains query parameters
-   [ ]  **`externalTenantId` stored durably** — all future operations reference this ID
-   [ ]  **Onboarding completion confirmed** before case submission — via `client.onboarding.contract_signed` webhook or polling `GET /clients/{externalTenantId}` for `onboardingDone: true`
-   [ ]  **Link request expiry handled** — 409 approval URLs expire after a configurable per-partner TTL (`ApprovalTtlDays`, default 7 days, clamped 1–30 days). Subscribe to `client.link_expired` to detect expiry; resubmit `POST /clients` with the same `externalTenantId` to generate a fresh approval URL.

<a id="case-submission"></a>

### Case Submission

-   [ ]  **Required fields validated** — `currencyCode`, `date`, a positive total via `amountToRecover` or `claimLines`, `debtor.type`, `debtor.name`, `debtor.address`, and `debtor.city`. Identify the country with `debtor.countryAlpha2` (preferred) or `debtor.country`; US debtors also need `debtor.stateAlpha2` (preferred) or `debtor.state`. (`dueDate` is optional.)
-   [ ]  **`creditorReference` unique per creditor and test/live classification** — duplicates return `422`. Use it for duplicate prevention and use the [`Idempotency-Key` header](https://docs.debitura.com/developer-concepts/idempotency.md) for safe response replay.
-   [ ]  **`isTest` omitted or `false`** on production submissions — `true` creates classified test data and does not bypass validation or business-error responses.
-   [ ]  **Revenue attribution understood** — new cases inherit the creditor's active referral link regardless of Bearer or `XApiKey` authentication. Revenue follows the link's referral terms; Bearer authentication additionally records referral-specific creation metadata. See [Attribution](https://docs.debitura.com/referral-partners/concepts/attribution.md).

<a id="error-handling"></a>

### Error Handling

-   [ ]  **`422 MissingDebtCollectionContract`** — catch and present `solutionUrl` for SDCA signing, then retry
-   [ ]  **`422 MissingPowerOfAttorney`** — catch and present `solutionUrl` for PoA/JPA signing, then retry. This also covers [jurisdiction pricing zones](https://docs.debitura.com/referral-partners/concepts/jurisdiction-pricing-carveouts.md).
-   [ ]  **`422 MissingKycVerification`** — catch and present `solutionUrl` for the KYC form. **Not bypassed by `allowPendingContracts`**. See [KYC Verification](https://docs.debitura.com/referral-partners/integration-guides/kyc-verification.md).
-   [ ]  **No-partner-available jurisdiction** — this does not currently return a typed `NoPartnerAvailable` business error; the case-creation endpoint returns an untyped legacy field-error dict (e.g. `{"BusinessRule": ["We don't have an exclusive pre-legal partner..."]}`). Detect it by message content and show a "jurisdiction not supported" message. Do not auto-retry.
-   [ ]  **Blocked creditor account** — returns `422` with `businessErrors[].type: CreditorBlocked` and the block reason in the message. A non-signing block has no `signingHandoff`. Surface it to support; auto-retry will not resolve it.
-   [ ]  **Return URL on all `solutionUrl` redirects** — without it, clients complete signing with no way back to your platform
-   [ ]  **`429` rate limit** — read `retryAfter` from response and wait. Limits: 2,000/min, 20,000/hr, 100,000/day per API key.

See the [Error Reference](https://docs.debitura.com/referral-partners/error-reference.md) for the full list of errors across both APIs.

<a id="webhooks"></a>

### Webhooks

-   [ ]  **HTTPS endpoint registered** — HTTP, localhost, and private IPs are rejected. Only ports 443 and 8443 are allowed.
-   [ ]  **Production signing secret saved** at subscription creation — it is never returned again and differs from your test secret. See [Webhooks](https://docs.debitura.com/referral-partners/integration-guides/webhooks.md).
-   [ ]  **HMAC-SHA256 verification** is computed over `{timestamp}.{payload}` (the raw request body, not re-serialized JSON, dot-joined with the timestamp) with the secret Base64-decoded. See [Signature Verification](https://docs.debitura.com/developer-concepts/webhooks.md#signature-verification).
-   [ ]  **Timestamp validation** — reject events older than 5 minutes to prevent replay attacks
-   [ ]  **10-second response time** — acknowledge immediately, process asynchronously. 8 consecutive failures auto-disable the subscription.
-   [ ]  **Idempotency** — deduplicate using `event.id`. Debitura uses at-least-once delivery. See [Production practices](https://docs.debitura.com/referral-partners/integration-guides/webhooks.md#production-practices).
-   [ ]  **All required events subscribed** — at minimum: `client.onboarding.contract_signed`, `client.linked`, `client.link_requested`, `client.link_expired`, `case.created`, `case.updated`, `case.closed`

<a id="kyc-readiness"></a>

### KYC Readiness

-   [ ]  **`POST /cases/preview`** called before submission to detect KYC requirements proactively. The Referral Partner preview returns `isEligible`, `ineligibilityReason`, `jurisdiction`, `pricingPreview`, and `requiresKycVerification` — inspect `requiresKycVerification` to drive your KYC flow. (Unlike the Customer API preview, the Referral Partner preview does not return `requiredActions`.)
-   [ ]  **KYC tested with bearer tokens** — direct `XApiKey` calls skip KYC checks entirely, so testing with `XApiKey` will not exercise your KYC flow

<a id="end-to-end-validation"></a>

### End-to-End Validation

Run these flows in the test environment before switching to production:

-   [ ]  **New client onboarding** — `POST /clients` → present URL → client completes SDCA signing → webhook fires → mint token → submit case
-   [ ]  **Existing client linking (409)** — `POST /clients` with known email → present approval URL → client approves → webhook fires → retry
-   [ ]  **Case with missing PoA** — submit case to a PoA-required jurisdiction → get 422 → present signing URL → sign → retry → case created
-   [ ]  **KYC flow** — submit case to a KYC-required partner → get 422 → present KYC form → complete → retry → case created
-   [ ]  **Webhook signature verification** — call `POST /v1/webhooks/test` once per event type (the endpoint fires a single event type per call, set by the `eventType` field) and confirm your handler accepts each one

Clean test state

Use `DELETE /clients/{externalTenantId}` to [reset test clients](https://docs.debitura.com/referral-partners/getting-started/environments.md#reset-test-clients) between test runs (test environment only).
