Source: https://docs.debitura.com/referral-partners/integration-guides/starter-integration

# Build the collection button

The Starter Integration puts a "Send to collection" button beside an unpaid invoice. Your server sends the invoice to Debitura in one request. Debitura works out what the client still has to do (sign up, approve the connection, sign an agreement, verify identity or fix the invoice) and returns one link to open. You follow the request until it becomes a case.

**Use this when:** you want collection in your product without building onboarding, agreement or error-handling screens. **You'll build:** one server call, a button that opens a link, and one webhook handler. New to Starter? Do the [quickstart](https://docs.debitura.com/referral-partners/getting-started/starter-quickstart.md) first.

<a id="how-it-works"></a>

## How it works

Every time the client finishes a step, the request moves on and, if more is needed, carries a new `solutionUrl`. Your button always does the same thing: open the current `solutionUrl`.

<a id="1-send-one-invoice"></a>

## 1\. Send one invoice

Call `POST /collection-requests` from your server with your [API key](https://docs.debitura.com/referral-partners/getting-started/authentication.md). Never call it from browser code. The [API reference](https://docs.debitura.com/api/referral-partner-api/collection-requests.md) lists every field.

```http
POST https://testreferral-api.debitura.com/collection-requests
XApiKey: <your-test-partner-key>
Idempotency-Key: collection-example-inv-0042
Content-Type: application/json

{
  "externalTenantId": "example-client-42",
  "client": {
    "name": "Example Client Ltd",
    "country": "GB",
    "supportEmail": "accounts@example.invalid"
  },
  "user": {
    "name": "Example User",
    "email": "accounts@example.invalid"
  },
  "invoices": [{
    "creditorReference": "EXAMPLE-INV-0042",
    "debtor": {
      "type": "Company",
      "name": "Example 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
  }]
}
```

What to know about the request:

-   **One invoice per request.** `invoices` is an array with exactly one item. If your user selects several invoices, send one request each.
-   **Your identifiers.** `externalTenantId` is your stable ID for the client, and `creditorReference` is the invoice number. You use both to look a request up later.
-   **Client details are used once.** `client` and `user` set up a new account. They never overwrite an account that already exists.
-   **Retries are safe** when you reuse the same `Idempotency-Key`. For 24 hours, the same key returns the original response; a changed payload with that key is refused. Because it is the _original_ response, it can show an earlier step than where the client is now, so use a [current read](https://docs.debitura.com/referral-partners/integration-guides/starter-integration.md#3-follow-progress) to check progress.
-   **Return navigation** after the hosted pages is set on your partner account, not per request. Never build onboarding or signing URLs yourself.

<a id="2-open-the-next-action"></a>

## 2\. Open the next action

The response says where the request stands and, if the client has something to do, gives you the link. For a new client:

```json
{
  "id": "33333333-3333-4333-8333-000000000042",
  "status": "awaiting_onboarding",
  "solutionType": "onboarding",
  "solutionUrl": "https://testreferral.debitura.com/Onboarding/CompanyDetails/55555555-5555-4555-8555-555555555555",
  "externalTenantId": "example-client-42"
}
```

Store the request `id`, then open `solutionUrl` from your button. What each status means for your user:

| `status` | What the client does next | What your app shows |
| --- | --- | --- |
| `awaiting_onboarding` | Sets up their Debitura account | Opens `solutionUrl` |
| `awaiting_approval` | Approves the connection to your platform (they already have a Debitura account) | Opens `solutionUrl`; Debitura has also emailed them the invitation |
| `awaiting_signature` | Signs the agreement named in `solutionType` | Opens `solutionUrl` |
| `awaiting_kyc` | Submits identity details | Opens `solutionUrl` |
| `needs_fixing` | Corrects the invoice details and submits the draft | Opens `solutionUrl`. Saving alone creates no case |
| `submitted` | Nothing; the invoice is a case | Opens `solutionUrl` to show the case |
| `processing` | Nothing yet | Shows "in progress" and reads again; there may be no link |
| `rejected`, `expired` | Nothing | Shows the returned reason; there is no link, so don't make one |

Details that matter:

-   **Signatures.** `solutionType` tells you which agreement: `sdca`, `sdca_update`, `power_of_attorney` or `jurisdiction_pricing_appendix`.
-   **Existing clients.** When the matched account isn't linked to you yet, nothing is created until the client approves. Debitura emails one approval invitation to the submitting user, and the same link is your `solutionUrl`. Until they approve, the response doesn't reveal which account matched. Only approvals expire (normally after 7 days); onboarding, signing and drafts have no deadline from the request.
-   **KYC.** The case waits while identity details are missing. Submitting them releases it; the collecting partner's review of those details is a separate, later step.
-   **`submitted` is not "collecting".** The invoice's `caseStatus` can still show verification or another early case stage.
-   **HTTP codes.** `201` means submitted, `202` means action or processing remains, and `422` can mean rejected. Branch on the body's `status`, not on the HTTP code alone.

**Business context:** see [Case eligibility](https://support.debitura.com/en/articles/13638265-case-eligibility-what-types-of-debt-debitura-accepts-and-minimum-requirements) for which invoices Debitura accepts.

<a id="3-follow-progress"></a>

## 3\. Follow progress

Read the current state by request ID, or find the newest request for a client and invoice:

```http
GET https://testreferral-api.debitura.com/collection-requests/{requestId}
XApiKey: <your-test-partner-key>
```

```http
GET https://testreferral-api.debitura.com/collection-requests?externalTenantId=example-client-42&creditorReference=EXAMPLE-INV-0042
XApiKey: <your-test-partner-key>
```

To hear about changes without polling, subscribe to [`collection_request.updated`](https://docs.debitura.com/referral-partners/integration-guides/webhooks.md#collection_requestupdated). It fires when the request status or the invoice outcome changes, and carries the current request. Case events (`case.created`, `case.updated`, `case.closed`) keep working as usual. [Verify signatures and deduplicate](https://docs.debitura.com/developer-concepts/webhooks.md#signature-verification) as for every Debitura webhook.

Two things to plan for:

-   **Delivery is best effort and can repeat.** If a webhook seems missing, read the request. Never create a new case because a callback didn't arrive.
-   **Webhooks and test data.** Request updates reach your active subscriptions in both Test and Production; an invoice's `isTest` does not decide where they go. A [webhook test](https://docs.debitura.com/referral-partners/integration-guides/webhook-testing.md) with `collectionRequestId` reaches Test subscriptions only, and only in the test environment.

<a id="4-handle-failures"></a>

## 4\. Handle failures

| What happens | What it means | What to do |
| --- | --- | --- |
| `400` | The request itself is unreadable: malformed JSON, wrong types, missing `externalTenantId` or `creditorReference`, more than one invoice, or size limits | Fix your request; nothing was stored |
| `needs_fixing` | The invoice is readable but needs correcting | Open `solutionUrl`; the client fixes it on Debitura |
| `rejected` | Debitura can't take this invoice, e.g. the country isn't covered or the amount is below the minimum | Show the returned reason |
| Timeout or `5xx` | A dependency failed | Retry with the same `Idempotency-Key`, or read the request first. Don't tell your user it worked |

<a id="5-add-full-endpoints-when-you-need-them"></a>

## 5\. Add Full endpoints when you need them

Starter and Full share the same client relationship. With the same `externalTenantId`, you can [mint a bearer token](https://docs.debitura.com/referral-partners/integration-guides/case-submission.md) and use Customer API operations for this client at any time, with no new onboarding. Typical next steps:

-   [Preview pricing](https://docs.debitura.com/referral-partners/integration-guides/preview-case-pricing.md) to show the fee before your user clicks
-   [Case status, documents and messages](https://docs.debitura.com/clients/integration-guides/track-case-status.md) inside your own screens

A new Starter request recognises an existing case for the same client, invoice reference and test/live classification, whichever route created it. It returns that case and leaves the case's origin, attribution and rate unchanged. Starter doesn't change how the Full endpoints respond.

<a id="try-it-without-code"></a>

## Try it without code

The [Ledgerline demo](https://referral.debitura.com/demo-journey#starter) shows the button in a fictional accounting product. Turn on **Developer view** to see example requests and responses for each step. The demo sends no API traffic, so it doesn't prove your own integration works; verify that against test before production.

<a id="whats-next"></a>

## What's next

-   [Go live](https://docs.debitura.com/referral-partners/going-live-checklist.md): the Starter checklist
-   [Who does what](https://docs.debitura.com/referral-partners/concepts/responsibility-matrix.md): Starter and Full side by side
-   [Errors](https://docs.debitura.com/referral-partners/error-reference.md#collection-requests-starter-integration): collection-request errors

## Diagrams

```mermaid
sequenceDiagram
    autonumber
    actor U as Your user
    participant A as Your app
    participant D as Debitura
    U->>A: Clicks "Send to collection"
    A->>D: POST /collection-requests (one invoice)
    D-->>A: status + solutionUrl
    A->>U: Opens solutionUrl
    U->>D: Signs up, approves, signs or fixes, on Debitura's pages
    D-->>A: collection_request.updated (webhook)
    A->>D: GET /collection-requests/{id}
    D-->>A: status: submitted, invoice has a case
```
