Create and onboard a new client
POST/clients
Creates a new client (creditor) in the Debitura platform and links them to the authenticated referral partner.
Request Structure
- ExternalTenantId (required) - Your unique identifier for this client (for correlation and future lookups)
- Client (required) - Company information (name, registration number, country, address, contact details)
- Users (required, 1-N) - At least one user with email and name. For multiple users, exactly one must have IsOnboardingUser=true. Single-user requests auto-infer the onboarding user.
- Cases (optional) - Optionally create multiple collection cases during client creation (validated upfront to prevent orphaned clients)
Onboarding Flow
-
New Client (201/202)
- Client and users are created in Debitura
- ReferralPartnerClientLink is established with revenue sharing percentage
- If onboarding is complete (terms signed), returns 201
- If onboarding pending (terms not signed), returns 202 with OnboardingLinks.Url for completing the process
202 Response - Two URL Scenarios:
1a. New Client - Full Onboarding URL
- Scenario: Client has never signed the SDCA (Standard Debt Collection Agreement)
- URL Pattern:
{onboardingBase}/companydetails/{referralPartnerClientLinkId} - User Journey: Multi-step onboarding (company details → users → sign SDCA)
- Use Case: First-time client registration
1b. Existing Client - Contract Upgrade URL
- Scenario: Client previously signed SDCA but terms have been updated (NeedsRefresh=true)
- URL Pattern:
{onboardingBase}/ContractUpgrade/Sign/{referralPartnerClientLinkId} - User Journey: Streamlined contract re-signing only (no company details re-entry)
- Use Case: SDCA version upgrade (e.g., new pricing tiers, updated legal terms)
- Note: This can happen to previously-ready clients (201 → 202 state transition)
Important: The
POST /clientsendpoint is idempotent and re-checks SDCA status on every call. This means an existing client that previously returned201 Createdmay flip to202 Acceptedif Debitura releases a new SDCA version requiring re-signature. -
Existing Client - Needs Linking (409 Conflict) There are TWO distinct 409 conflict scenarios - check the ConflictResponse.Type field to distinguish:
2a. ClientExistsNeedsLinking (Type: "ClientExistsNeedsLinking")
- Client already exists in Debitura (matched by user email or support email)
- A link request is created with an expiration window configured per-partner (
ApprovalTtlDays, default 7 days, clamped 1–30) - Existing client must approve the referral partner link via OnboardingLinks.Url
- If approved, IsAttributedClient will be FALSE (revenue only on partner-referred cases)
- Cases submitted in the original request are persisted and replayed against the linked creditor automatically when the user approves.
AllowPendingContracts=trueis forced on replay so cases land inPendingContractSigningrather than 422-failing on missing SDCA/PoA/KYC. - Returns 409 with OnboardingLinks.Url pointing to approval page
2b. ClientAlreadyLinkedToAnotherPartner (Type: "AlreadyLinkedToAnotherPartner")
- Client is already linked to a DIFFERENT referral partner
- Only one referral partner link per client is supported
- Cannot proceed - contact Debitura support for resolution
- Returns 409 with error message and support contact
-
Idempotency
- Repeated calls with same ExternalTenantId return existing client status (201 or 202)
- No duplicate clients or links are created
-
Previously Withdrawn Client - Re-linked (201/202)
- Applies when you re-submit an ExternalTenantId you previously withdrew via POST /clients/{externalTenantId}/withdraw, AND the re-submission still identifies that same client — that is, it carries a user email or supportEmail already registered on it
- The ORIGINAL client is re-linked rather than duplicated: a new active link is created on the same Debitura client, IsAttributedClient stays true, and the archived link is retained for audit
- Cases in the re-submission are created against that client. A CreditorReference used by a case that the withdrawal closed can be reused — such a case no longer reserves it
- Any approval request still pending for this ExternalTenantId is resolved as declined, and a client.link_declined webhook is sent for it
- Falls back to the 409 handling in scenario 2 if the ExternalTenantId now resolves to a DIFFERENT client, if that client has since linked to another partner, or if the withdrawn link was not attributed to you
- Creates a new client as in scenario 1 — no re-link, no 409 — if the re-submission carries no contact email we recognise. A matching email is our only independent confirmation that this is the same client; without one we cannot tell a genuine re-submission apart from the same ExternalTenantId being reused for somebody else
- The re-link does not update the client or add users. Client details and Users in the re-submission are ignored, and the new link keeps the original onboarding user — send a new contact through the normal user-invitation flow instead
Response Codes
- 201 Created - Client created and fully onboarded (terms signed, ready to create cases, IsAttributedClient=true)
- 202 Accepted - Client created but onboarding incomplete (OnboardingLinks.Url provided to complete, IsAttributedClient=true)
- 400 Bad Request - Validation errors (missing required fields, invalid data, duplicate CreditorReferences within request). Most validation failures return a single-message ApiErrorResponseDto. Field-length violations (Client.Name, Client.SupportPhone, Client.RegistrationNumber, Client.SupportEmail, Users[].Email) are the one exception: they return a field-keyed error dictionary instead, e.g. { "Client.Name": ["Name must not exceed 80 characters (received 95)."] }, so multiple field problems can be reported together in one round-trip.
- 409 Conflict - Two scenarios (check ConflictResponse.Type):
- "ClientExistsNeedsLinking" - Client exists, needs approval link (if approved, IsAttributedClient=false)
- "AlreadyLinkedToAnotherPartner" - Client already linked to different partner (cannot proceed)
- 422 Unprocessable Entity - Business rule violation (field validation errors only, NOT partner matching failures)
- 500 Internal Server Error - Unexpected server error
Optional Multi-Case Creation If the Cases array is provided in the request:
- ALL cases are validated BEFORE client creation (checks field validation and duplicate references)
- Client is ALWAYS created to ensure referral partner link and future attribution
- Cases with available collection partners are created successfully (CaseResults.SuccessfulCases)
- Cases without available partners are NOT created and reported as failures (CaseResults.FailedCases)
- If validation errors exist (primitives, duplicates), client creation is aborted and 400 is returned
- Successful cases appear in CaseResults.SuccessfulCases with full case details
- Failed cases appear in CaseResults.FailedCases with CaseIndex, CreditorReference, and error details (e.g., "No collection partner available for jurisdiction")
Claim Amount and Aging on each case Each entry in Cases accepts the claim amount in one of three ways:
amountToRecoverplus a singledueDateamountToRecoverplus the cumulativeamountToRecoverOver6/12/24MonthsbucketsclaimLines[]— send the unpaid invoices and let us do the arithmetic (recommended for multi-invoice claims)
"claimLines": [
{ "dueDate": "2024-01-15", "amount": 423.42, "reference": "INV-1001" },
{ "dueDate": "2025-05-02", "amount": 700.87, "reference": "INV-1042" }
]
amountis the outstanding balance on that invoice, already net of payments and credit notes.- We derive
amountToRecoverand all three age buckets from the lines, so sendclaimLinesinstead ofamountToRecoverand the bucket fields. Sending both is a 400. - If you omit the case-level
dueDate, it is set to the oldest due date across that case's lines; an explicitdueDateis honoured. - Maximum 1000 lines per case, and a maximum of 1000 lines in total across all entries in Cases. Per-line errors are keyed by case and line index, e.g.
Cases[0].ClaimLines[2].DueDate. claimLinesis a pricing input only — it is not stored and is not shown to the collecting partner.
User Roles
- IsOnboardingUser=true - User receives CreditorAdmin role (full access)
- IsOnboardingUser=false - User receives CreditorUser role (limited access)
Revenue Sharing (Fee Percentage Locked at Link Creation)
- The referral fee percentage is snapshot from the partner's current configuration at the exact moment the client link is created
- This percentage is IMMUTABLE and will NEVER change for this client - even if the partner's global fee percentage is updated later
- The locked percentage is used for ALL revenue calculations for ALL cases created by this client, forever
- This ensures predictable, stable revenue sharing and prevents disputes over retroactive fee changes
- To see the locked percentage for a specific client, use GET /clients/{externalTenantId} (included in response)
Request
Responses
- 201
- 202
- 400
- 409
- 422
- 500
Client created and fully onboarded (terms signed)
Client created but onboarding incomplete (use OnboardingLinks.Url to complete)
Invalid request (validation errors). Field-length violations (Client.Name, Client.SupportPhone, Client.RegistrationNumber, Client.SupportEmail, Users[].Email) return this field-keyed error dictionary, e.g. { "Client.Name": ["Name must not exceed 80 characters (received 95)."] }. Most other validation failures on this endpoint instead return the single-message ApiErrorResponseDto shape.
Client already exists - approval required to link (use OnboardingLinks.Url for approval)
Business rule violation (field validation errors only)
Internal server error