Source: https://docs.debitura.com/referral-partners/getting-started/starter-ai-integration-recipe

# Build a Starter Integration with an AI agent

Build a “Send to collection” button: send one invoice from your server, open the returned link, then read current progress. Debitura hosts setup and correction. Pricing preview is optional.

<a id="give-your-agent-this-brief"></a>

## Give your agent this brief

Start at [llms.txt](https://docs.debitura.com/llms.txt). Append `.md` to any documentation URL for its Markdown copy, including this recipe. Use the [collection-request reference](https://docs.debitura.com/api/referral-partner-api/collection-requests.md) and [OpenAPI schemas](https://docs.debitura.com/assets/files/apis-ae4b8396e058fd1e5d37994844a8a578.json) for the complete contract.

```text
Build a small server-side Debitura Starter Integration using this recipe
and its linked docs. Use test hosts, fictional clients and isTest invoices.
Keep credentials on the server, outside prompts, code, browser bundles and logs.
Implement one-invoice POST, a user-clicked returned solutionUrl, current GET,
and a signature-verified collection_request.updated handler with safe deduplication.
Recover after return, repeated/missing events, failed reads and uncertain POSTs.
Record actual request/case progress; redirects and submitted are not proof of
active collection. Exercise the checks below and record friction and cleanup.
```

<a id="1-prepare-test-access"></a>

## 1\. Prepare test access

Set your server’s `DEBITURA_API_KEY` to a test partner key. Call `https://testreferral-api.debitura.com` with `XApiKey`; check access with `GET /me`. Arrange an allowlisted test email and verification-code access with your partnership contact. Use unique fictional identities. See [Environments and test data](https://docs.debitura.com/referral-partners/getting-started/environments.md).

The public `123456` demo is a simulation. A demo partner alone does **not** enable that code for API-created clients. Use their real test verification codes; never update agreement state in the database to claim completion.

<a id="2-send-one-invoice-from-your-server"></a>

## 2\. Send one invoice from your server

Use one stable `externalTenantId` per client and `creditorReference` per invoice. Replace the test email placeholders with the arranged address and `RUN_ID` with your unique run identifier:

```http
POST https://testreferral-api.debitura.com/collection-requests
XApiKey: YOUR_TEST_API_KEY
Idempotency-Key: starter-RUN_ID-001
Content-Type: application/json

{
  "externalTenantId": "starter-RUN_ID",
  "client": {
    "name": "Starter Recipe Test Ltd",
    "country": "GB",
    "supportEmail": "YOUR_TEST_EMAIL"
  },
  "user": { "name": "Recipe Test User", "email": "YOUR_TEST_EMAIL" },
  "invoices": [{
    "creditorReference": "STARTER-RUN_ID-001",
    "debtor": {
      "type": "Company",
      "name": "Fictional Debtor Ltd",
      "countryAlpha2": "GB",
      "address": "10 Example Street",
      "city": "London"
    },
    "amountToRecover": 1500.00,
    "currencyCode": "GBP",
    "date": "2026-06-01T00:00:00Z",
    "dueDate": "2026-06-30T00:00:00Z",
    "isTest": true
  }]
}
```

`invoices` has **exactly one item**. Client/user fields initialise new accounts only. Configure return navigation on your partner account; omit `returnUrl` and never construct hosted URLs. For bulk sending, reuse [Sending several invoices](https://docs.debitura.com/referral-partners/integration-guides/starter-integration.md#sending-several-invoices): independent calls/results, deterministic current-action selection and retained partial failures.

Store request `id`, client/reference and original key/body in your existing server records. Authorise ownership on every browser-facing read; browsers cannot choose another client’s request or credentials.

<a id="3-open-the-returned-action-and-read-again"></a>

## 3\. Open the returned action and read again

A new client returns `202` / `awaiting_onboarding`, `solutionType: "onboarding"` and a `solutionUrl`. Show a user-clicked Continue link; asynchronous popups can be blocked. Open only the current returned HTTPS URL, without adding parameters.

| Current `status` | Your integration does |
| --- | --- |
| `awaiting_onboarding` | Open onboarding; complete company/user details and agreements. |
| `awaiting_approval` | Open approval. Existing clients must consent before case creation; Debitura emails the submitting user. |
| `awaiting_signature` | Open the agreement link; `solutionType` identifies `sdca`, `sdca_update`, `power_of_attorney` or `jurisdiction_pricing_appendix`. |
| `awaiting_kyc` | Open KYC. Submission releases eligible cases; reconciliation can take time. |
| `needs_fixing` | Open correction. Saving leaves a draft; explicit submission creates the case. |
| `submitted` | Show the case and `caseStatus`; ordinary verification can remain. |
| `processing` | Wait and refresh, without navigation. |
| `rejected` / `expired` | Show reason/issues without navigation. A fresh request can seek approval after expiry. |

Refresh null URLs and handle unknown actions explicitly. Agreements can be reused; another collector/jurisdiction can require more signing. Only approvals expire, normally after seven days. See [the complete action guide](https://docs.debitura.com/referral-partners/integration-guides/starter-integration.md#2-open-the-next-action).

Read current state **after every return**, on manual recheck while pending, and after a verified update:

```http
GET https://testreferral-api.debitura.com/collection-requests/{requestId}
XApiKey: YOUR_TEST_API_KEY
```

If the original response was lost, look up the newest request for that client and invoice; URL-encode both values:

```http
GET https://testreferral-api.debitura.com/collection-requests?externalTenantId=starter-RUN_ID&creditorReference=STARTER-RUN_ID-001
XApiKey: YOUR_TEST_API_KEY
```

GET defines progress; redirects do not. After shared setup, refresh **all known selected request IDs**. Clear Continue during refresh; failed reads retain the last result with an error and withhold stale navigation.

<a id="4-handle-updates-and-recovery"></a>

## 4\. Handle updates and recovery

[Register a webhook](https://docs.debitura.com/referral-partners/integration-guides/webhooks.md#create-a-webhook-subscription) on the **test** Referral Partner API (`POST /v1/Webhooks`), with your HTTPS endpoint, `events: ["collection_request.updated"]` and `isTestMode: true`. Save its returned signing secret on the server. Normal request updates can reach both Test and Production subscriptions regardless of the invoice's `isTest`; explicit [test deliveries](https://docs.debitura.com/referral-partners/integration-guides/webhook-testing.md) target Test subscriptions only.

Implement this handler using the [signature verification](https://docs.debitura.com/developer-concepts/webhooks.md#signature-verification) and [deduplication guidance](https://docs.debitura.com/referral-partners/integration-guides/webhooks.md#production-practices):

1.  Verify `X-Debitura-Signature` **before** parsing or acting. Sign `{timestamp}.{raw_json_body}` with HMAC-SHA256 using the Base64-decoded secret; compare lowercase hex in constant time. Reject invalid signatures, timestamps older than 300 seconds or more than 30 seconds ahead.
2.  Parse the verified body: type `event.event`, identity `event.id`, request ID `event.data.id`. Resolve your own client/request mapping; fetch from your configured API, never a supplied URL.
3.  Deduplicate `event.id` in your existing job/store. Durably enqueue before acknowledging, or complete GET/update before marking done and returning `2xx`. Failed work stays retryable. Return within 10 seconds; queue longer work.
4.  GET with the matching server-side partner key and update only that invoice row. Duplicates create no case/payment; current reads prevent out-of-order events regressing state.

SDCA → PoA can change GET without an event. Deliveries can repeat or be missed: retain return/manual GET recovery, with no exactly-once or zero-loss assumption.

| Failure | Recovery |
| --- | --- |
| Timeout / `5xx` during POST | Look up by client/reference, or retry the **original body and key** within the 24-hour replay window. Keep an uncertain outcome visible. |
| Same-key replay shows old action | GET current state; replay returns the original receipt, not progress. Changed body with the same key is refused. |
| `400` / unstructured HTTP error | Show the failure for that invoice. Fix malformed requests; do not treat them as stored requests. |
| `422` with a collection-request body | Handle its returned `status` and invoice reason; a structured rejection is a result. Other `422` errors can be idempotency conflicts, not receipts. |
| Failed read or dependency | Keep pending/error state, retry the read/work, and report no success until observed. |

<a id="5-verify-clean-up-and-go-live"></a>

## 5\. Verify, clean up and go live

Record HTTP status, request ID, invoice result and actual case status, without keys, signing links, verification codes or personal payloads. Exercise each check with fictional test fixtures:

-   New client → actual onboarding/signing → current GET; existing client → approval before processing.
-   Additional signature and KYC where required; corrected draft stays `needs_fixing` after save and creates a case only after explicit submit; rejected invoice retains its reason.
-   Identical keyed retry and changed-body conflict; reference lookup after an uncertain POST; current GET after return/missing event and stale replay; no duplicate case.
-   Valid signed update, repeated delivery, invalid signature/raw body, stale/future timestamp, failed GET followed by retry. Local signed fixtures prove your handler, not actual Debitura delivery; test delivery separately.
-   Invalid key, empty/two-item invoice array, another partner's request/tenant and unavailable dependency are refused or surfaced without leaking secrets or claiming success.

Use the supported [test reset](https://docs.debitura.com/referral-partners/getting-started/environments.md#reset-test-clients), inspecting blockers and closing active owned test cases first. Complete the [Starter go-live checklist](https://docs.debitura.com/referral-partners/going-live-checklist.md#starter-integration-checklist): production credentials/hosts and subscriptions, branding/return configuration, every status and recovery path. Real production invoices omit `isTest` or set it to `false`; this recipe performs no production calls.

Add [Full endpoints](https://docs.debitura.com/referral-partners/integration-guides/case-submission.md) later: mint a client bearer with the same `externalTenantId`, without new onboarding. Starter finds existing cases by client, invoice reference and test/live classification whichever route created them. The [Full AI recipe](https://docs.debitura.com/referral-partners/getting-started/ai-integration-recipe.md) remains available.
