Source: https://docs.debitura.com/api/referral-partner-api/clients

# Clients — Referral Partner API

Base URL: `https://referral-api.debitura.com`

Authentication: `XApiKey` API key; see [authentication](https://docs.debitura.com/developer-concepts/authentication.md).

Generated from [OpenAPI](https://docs.debitura.com/openapi/referral-partner-api.json). Examples are schema illustrations, not observed responses. Complete schemas, including recursive types, are in OpenAPI.

<a id="list-all-linked-clients"></a>

## List all linked clients

`GET /clients`

Retrieves a paginated list of all clients (creditors) linked to the authenticated referral partner.

Response Data
For each client, the response includes:
- **ExternalTenantId** - Your unique identifier for this client
- **OnboardingDone** - Whether the client has completed onboarding (signed debt collection agreements)
- **OnboardingLinks** - If onboarding incomplete, contains URL to complete the process
- **Client** - Complete client information (ID, company name, registration number, country, address, contact details)
- **Users** - List of all users associated with this client (ID, email, name)

Filtering Parameters
- **ExternalTenantId** - Filter to specific client by your identifier
- **IsAttributedClient** - Filter by attribution status (true = created by you, false = linked later)
- **DateCreatedFrom** - Filter clients linked on or after this date (ISO 8601 format)
- **DateCreatedTo** - Filter clients linked on or before this date (ISO 8601 format)
- **Query** - Search across company name, email, and registration number (case-insensitive)

Pagination
- **Page** - Page number (default: 1, min: 1)
- **PageSize** - Results per page (default: 50, min: 1, max: 100)
- Response includes page metadata: total count, current page size, skip count

Sorting
- **Sort** - Sort field and direction (format: 'field:direction')
- Supported fields: dateCreated, name
- Examples: 'dateCreated:desc', 'name:asc'
- Default: dateCreated:desc (most recent first)

Use Cases
- List all your clients for dashboard display
- Search for specific client by name, email, or registration number
- Filter clients by onboarding status
- Identify clients created by you vs. existing clients you linked
- Monitor client link creation dates
- Paginate through large client lists

Client Attribution and Revenue Rules ⚠️ CRITICAL FOR REVENUE CALCULATIONS
- **IsAttributedClient=true** - Client was created through the referral partner API
  - Referral partner earns revenue on ALL cases (100% of cases)
  - This is the default for clients created via POST /clients

- **IsAttributedClient=false** - Client existed in Debitura before the link was established (409 conflict scenario)
  - Referral partner earns revenue ONLY on cases created through the referral partnership
  - Cases created directly by the client (not through partner) do NOT generate referral revenue
  - This protects pre-existing client relationships

**This distinction is the most important business rule for revenue calculations.** Always check IsAttributedClient when forecasting or reconciling revenue.

Only active (non-archived) client links are returned.

### Query parameters

- `Page` (integer): Page number (default: 1)
- `PageSize` (integer): Results per page (default: 50, max: 100)
- `Query` (string): Search query across CompanyName, OfficeEmail, and CompanyRegistrationNumber
- `ExternalTenantId` (string): Filter by exact external tenant ID
- `IsAttributedClient` (boolean): Filter by attribution status (true = attributed client, false = linked but not attributed)
- `DateCreatedFrom` (datetime): Filter by link creation date (from)
- `DateCreatedTo` (datetime): Filter by link creation date (to)
- `OnboardingDone` (boolean): Filter by onboarding status (true = completed, false = pending)
- `Sort` (string): Sort field and direction. Format: "field[:asc|desc]"
Supported fields: dateCreated, name
Examples: "dateCreated:desc", "name:asc"
Default: dateCreated:desc

### Response 200

Clients retrieved successfully

- `page` (object): Paging metadata describing a paged result set.
- `page.totalResults` (integer): Total number of records for the query (filtered or all as applicable).
- `page.pageSize` (integer): How many records are returned per page.
- `page.currentPage` (integer): Which page number is being shown, calculated from the number of skipped items.
- `page.responseCount` (integer): How many records are present in the current page.
- `page.totalPages` (integer): Total number of pages available given TotalResults and PageSize.
Returns 0 if PageSize is 0 rather than dividing by zero.
- `summary` (object): 
- `summary.totalClients` (integer): 
- `summary.attributedClients` (integer): 
- `summary.onboardingComplete` (integer): 
- `summary.onboardingPending` (integer): 
- `summary.totalCases` (integer): 
- `clients` (array of objects, nullable): List of linked clients
- `clients[].externalTenantId` (string, nullable): 
- `clients[].onboardingDone` (boolean): 
- `clients[].onboardingLinks` (object): 
- `clients[].onboardingLinks.url` (string, nullable): 
- `clients[].client` (object): 
- `clients[].client.id` (uuid): 
- `clients[].client.companyName` (string, nullable): 
- `clients[].client.officeEmail` (string, nullable): 
- `clients[].client.country` (string, nullable): 
- `clients[].client.address` (string, nullable): 
- `clients[].client.city` (string, nullable): 
- `clients[].client.zipCode` (string, nullable): 
- `clients[].client.companyRegistrationNumber` (string, nullable): 
- `clients[].users` (array of objects, nullable): 
- `clients[].users[].id` (integer): 
- `clients[].users[].email` (string, nullable): 
- `clients[].users[].firstName` (string, nullable): 
- `clients[].users[].lastName` (string, nullable): 
- `clients[].isAttributedClient` (boolean): 
- `clients[].dateLinked` (datetime): 
- `clients[].caseStats` (object): 
- `clients[].caseStats.casesTotal` (integer): 
- `clients[].caseStats.casesClosed` (integer): 
- `clients[].caseStats.earningsUsd` (number): 
- `clients[].kycStatus` (enum): KYC (Know Your Customer) verification status for a client linked to a referral partner.
Captures three distinct states that a simple boolean cannot express.
Sent as snake_case string values: "not_required", "pending", "verified".
  Values: `NotRequired`, `Pending`, `Verified`.
- `clients[].kycVerification` (object): 
- `clients[].kycVerification.directorFullName` (string, nullable): 
- `clients[].kycVerification.directorHomeAddress` (string, nullable): 
- `clients[].kycVerification.directorDateOfBirth` (date): 
- `clients[].kycVerification.dateCreated` (datetime): 
- `clients[].kycVerification.verificationStatus` (enum, nullable): Partner/staff-set review status (Processing/Completed) for this submission. Null = not yet
reviewed. Note: distinct from the sibling `ClientResponse.KycStatus` field, which
describes whether KYC data has been submitted at all.
  Values: `Processing`, `Completed`, `null`.
- `clients[].kycVerification.verificationStatusUpdatedAt` (datetime, nullable): When VerificationStatus was last set. Null until set.
- `clients[].caseResults` (object): Result of creating multiple cases during client creation.
Groups successful and failed case creation attempts.
- `clients[].caseResults.successfulCases` (array of objects, nullable): Cases that were created successfully.
Each element contains the full case details.
- `clients[].caseResults.successfulCases[].id` (uuid): 
- `clients[].caseResults.successfulCases[].dateCreated` (datetime): 
- `clients[].caseResults.successfulCases[].dateUpdated` (datetime, nullable): 
- `clients[].caseResults.successfulCases[].reference` (string, nullable): 
- `clients[].caseResults.successfulCases[].creditorReference` (string, nullable): 
- `clients[].caseResults.successfulCases[].creditorComments` (string, nullable): 
- `clients[].caseResults.successfulCases[].claimDescription` (string, nullable): 
- `clients[].caseResults.successfulCases[].grossAmount` (number): 
- `clients[].caseResults.successfulCases[].remainder` (number): 
- `clients[].caseResults.successfulCases[].interestFees` (number): 
- `clients[].caseResults.successfulCases[].reminderFees` (number): 
- `clients[].caseResults.successfulCases[].collectionFees` (number): 
- `clients[].caseResults.successfulCases[].totalAddedFees` (number): 
- `clients[].caseResults.successfulCases[].currency` (string, nullable): 
- `clients[].caseResults.successfulCases[].isTestCase` (boolean): 
- `clients[].caseResults.successfulCases[].lifecycle` (string, nullable): 
- `clients[].caseResults.successfulCases[].dueDate` (datetime): 
- `clients[].caseResults.successfulCases[].date` (datetime): 
- `clients[].caseResults.successfulCases[].dateFinished` (datetime, nullable): 
- `clients[].caseResults.successfulCases[].dateCollectionStarted` (datetime, nullable): 
- `clients[].caseResults.successfulCases[].closeCode` (string, nullable): 
- `clients[].caseResults.successfulCases[].currentEngagementPhase` (string, nullable): The current phase of the case's engagement: "Pre-legal", "Legal", or "Enforcement".
A different axis from Lifecycle/CloseCode — an Active case can be
in any of the three phases.
            
Null means "no active engagement" (e.g. lead / quoting / pre-contract-signing / unassigned, or
a data-consistency gap) — this is a distinct third state, NOT a synonym for Pre-legal. Most
cases legitimately read Pre-legal; phase only leaves Pre-legal on legal/enforcement quote flows.
            
Not guaranteed to be monotonic: an admin correction can move phase backwards (e.g. Legal back
to Pre-legal).
            
Persists after case closure — reflects the case's last-known engagement phase, not the current
Lifecycle. Note: this is a different field from a lead quote's own offered phase (the phase a
partner's quote proposes to work the case at, if this case ever went through a quote flow) —
this field is the case-level phase of its actual engagement, not a quote's terms.
- `clients[].caseResults.successfulCases[].claimType` (string, nullable): The type of claim for this case (e.g. "Unpaid Invoice", "Loan Repayment", "Breach of Contract").
Null if not set.
- `clients[].caseResults.successfulCases[].creditorDivisionId` (uuid, nullable): 
- `clients[].caseResults.successfulCases[].debtor` (object): V1 Debtor DTO for external partner APIs.
The debtor is the party that owes the debt.
- `clients[].caseResults.successfulCases[].debtor.type` (string, required): Debtor type. Valid values: "Company" or "Private" (case-insensitive)
- `clients[].caseResults.successfulCases[].debtor.name` (string, required): Debtor name (company name or person's full name)
- `clients[].caseResults.successfulCases[].debtor.contactPerson` (string, nullable): Contact person at the company (required for companies, not used for persons)
- `clients[].caseResults.successfulCases[].debtor.companyRegistrationNumber` (string, nullable): Company registration number (VAT number, CVR, org number, etc.)
- `clients[].caseResults.successfulCases[].debtor.address` (string, nullable): Street address
- `clients[].caseResults.successfulCases[].debtor.zipCode` (string, nullable): Postal/ZIP code
- `clients[].caseResults.successfulCases[].debtor.city` (string, nullable): City name
- `clients[].caseResults.successfulCases[].debtor.state` (string, nullable): State/region/province name
- `clients[].caseResults.successfulCases[].debtor.stateAlpha2` (string, nullable): US state: two-letter code (e.g., "CA"), ISO 3166-2 format (e.g., "US-CA"), or full name (e.g., "California")
- `clients[].caseResults.successfulCases[].debtor.countryAlpha2` (string, nullable): Country code (ISO 3166-1 alpha-2 format)
- `clients[].caseResults.successfulCases[].debtor.country` (string, nullable): Country name
- `clients[].caseResults.successfulCases[].debtor.email` (string, nullable): Email address for debtor contact
- `clients[].caseResults.successfulCases[].debtor.phone` (string, nullable): Phone number (include country code)
- `clients[].caseResults.successfulCases[].collectionPartner` (object): V1 Collection Partner DTO for external partner APIs
- `clients[].caseResults.successfulCases[].collectionPartner.name` (string, nullable): 
- `clients[].caseResults.successfulCases[].collectionPartner.officeEmail` (string, nullable): 
- `clients[].caseResults.successfulCases[].collectionPartner.officePhone` (string, nullable): 
- `clients[].caseResults.successfulCases[].collectionPartner.publicSite` (string, nullable): 
- `clients[].caseResults.successfulCases[].collectionPartner.surveyCadenceMode` (enum, deprecated): Deprecated: kept as a number and never removed, but not extended. Survey-generation cadence: 0 = Standard
(rolling monthly survey), 1 = DecisionPointOnly (no rolling surveys).
  Values: `0`, `1`.
- `clients[].caseResults.successfulCases[].creditor` (object): Creditor (client) information for external partner APIs.
Represents the party that the debtor owes money to.
- `clients[].caseResults.successfulCases[].creditor.id` (uuid): Unique identifier for the creditor
- `clients[].caseResults.successfulCases[].creditor.companyName` (string, nullable): Company name of the creditor
- `clients[].caseResults.successfulCases[].creditor.companyRegistrationNumber` (string, nullable): Company registration number (CVR, VAT number, etc.)
- `clients[].caseResults.successfulCases[].creditor.officeEmail` (string, nullable): Primary office email address
- `clients[].caseResults.successfulCases[].creditor.officePhone` (string, nullable): Primary office phone number
- `clients[].caseResults.successfulCases[].creditor.address` (string, nullable): Street address
- `clients[].caseResults.successfulCases[].creditor.city` (string, nullable): City
- `clients[].caseResults.successfulCases[].creditor.zipCode` (string, nullable): Postal/ZIP code
- `clients[].caseResults.successfulCases[].creditor.state` (string, nullable): State or region (if applicable)
- `clients[].caseResults.successfulCases[].creditor.country` (string, nullable): Country name
- `clients[].caseResults.successfulCases[].creditor.division` (object): Creditor division information for external partner APIs.
Represents a specific division or department within a creditor organization.
- `clients[].caseResults.successfulCases[].creditor.division.id` (uuid): Unique identifier for the division
- `clients[].caseResults.successfulCases[].creditor.division.name` (string, nullable): Name of the division
- `clients[].caseResults.successfulCases[].bankAccount` (object): Bank account information for partner API.
Full details provided as partners need this to:
1. Provide payment instructions to debtors (when debtor pays client directly)
2. Execute payouts to clients (when partner receives payment and pays out remainder)
- `clients[].caseResults.successfulCases[].bankAccount.id` (integer): Bank account identifier
- `clients[].caseResults.successfulCases[].bankAccount.label` (string, nullable): User-friendly label (e.g., "Main EUR Account")
- `clients[].caseResults.successfulCases[].bankAccount.scheme` (string, nullable): Account scheme: IBAN, SWIFT, or LOCAL
- `clients[].caseResults.successfulCases[].bankAccount.currencyCode` (string, nullable): Currency code (ISO 4217)
- `clients[].caseResults.successfulCases[].bankAccount.bankCountryCode` (string, nullable): Bank country code (ISO Alpha-2)
- `clients[].caseResults.successfulCases[].bankAccount.accountHolderName` (string, nullable): Account holder name (beneficiary)
- `clients[].caseResults.successfulCases[].bankAccount.iban` (string, nullable): IBAN (for IBAN scheme accounts)
- `clients[].caseResults.successfulCases[].bankAccount.bic` (string, nullable): BIC/SWIFT code (for IBAN and SWIFT scheme accounts)
- `clients[].caseResults.successfulCases[].bankAccount.accountNumber` (string, nullable): Account number (for SWIFT and LOCAL scheme accounts)
- `clients[].caseResults.successfulCases[].bankAccount.localIdentifier` (string, nullable): Local identifier (for LOCAL scheme accounts, e.g., sort code + account number)
- `clients[].caseResults.successfulCases[].bankAccount.localIdentifierType` (string, nullable): Type of local identifier (e.g., "Sort Code", "Routing Number")
- `clients[].caseResults.successfulCases[].bankAccount.bankName` (string, nullable): Bank name (optional)
- `clients[].caseResults.successfulCases[].bankAccount.bankAddress` (string, nullable): Bank address (optional)
- `clients[].caseResults.successfulCases[].bankAccount.bankCity` (string, nullable): Bank city (optional)
- `clients[].caseResults.successfulCases[].bankAccount.bankZipCode` (string, nullable): Bank zip/postal code (optional)
- `clients[].caseResults.successfulCases[].bankAccount.bankState` (string, nullable): Bank state/region (optional)
- `clients[].caseResults.successfulCases[].blendedAgeUpliftPoints` (number, nullable): MULTI-INVOICE AGE BUCKET PRICING
Calculated blended age uplift percentage points (0-20) for multi-invoice cases.
Shows the additional fee percentage added due to invoice age.
Formula: ((A12-A24)×10 + A24×20) / Total Principal
Null for single-invoice cases (age uplift is calculated from due date instead).
- `clients[].caseResults.successfulCases[].preLegalSuccessFee` (number, nullable): PRE-LEGAL SUCCESS FEE
The total pre-legal success fee percentage for this case.
Includes base fee + age-based uplift (blended or single-invoice).
Null if pricing has not been calculated yet or if case is not in pre-legal phase.
Example: 20.5 represents 20.5% success fee.
- `clients[].caseResults.successfulCases[].solutionUrl` (string, nullable, deprecated): When the case is created with allowPendingContracts=true and required contracts are unsigned,
this URL points to the signing page. Null when contracts are already signed or not applicable.
- `clients[].caseResults.successfulCases[].signingHandoff` (object): Partner-facing handoff metadata for a creditor's pending signing chain.
Returned on POST /cases responses (422 with pending-signing errors,
or 200 with AllowPendingContracts=true when signings remain).
            
Designed as an envelope so future fields (expiration, suggested email
copy, etc.) can be added without polluting the parent DTO.
- `clients[].caseResults.successfulCases[].signingHandoff.combinedSigningUrl` (string, nullable): Single signing entry URL that walks the creditor through every
pending step (SDCA upgrade → PoA → JPA → KYC) on the Creditors app
and returns to the partner-supplied returnUrl when done.
- `clients[].caseResults.successfulCases[].exclusivePeriodEndDate` (datetime, nullable): The date the exclusive collection period ends (or ended).
Null if no collection period has been created for this case (e.g. custom-terms cases).
Use GET /cases/{id}/exclusive-period for the full chain including extensions.
- `clients[].caseResults.successfulCases[].disputeStatus` (string, nullable): Whether the claim is disputed by the debtor.
One of: "Yes, the claim is disputed", "No, the claim is not disputed", or "Don't Know".
Null when the dispute status has not been set on the case.
- `clients[].caseResults.successfulCases[].validation` (object): Stable v1 validation summary used by ordinary and list mappings.
- `clients[].caseResults.successfulCases[].validation.needsInfo` (boolean): 
- `clients[].caseResults.successfulCases[].assignedUser` (object): Represents the creditor team member assigned to a case.
- `clients[].caseResults.successfulCases[].assignedUser.email` (string, nullable): The assigned user's email address.
- `clients[].caseResults.successfulCases[].assignedUser.name` (string, nullable): The assigned user's full name.
- `clients[].caseResults.successfulCases[].allocationOutstanding` (object): Outstanding amount per bucket on the case: each bucket's total minus the payments allocated to it.
- `clients[].caseResults.successfulCases[].allocationOutstanding.principal` (number): 
- `clients[].caseResults.successfulCases[].allocationOutstanding.interest` (number): 
- `clients[].caseResults.successfulCases[].allocationOutstanding.reminderFees` (number): 
- `clients[].caseResults.successfulCases[].allocationOutstanding.collectionFees` (number): 
- `clients[].caseResults.failedCases` (array of objects, nullable): Cases that failed during creation.
Each element contains error details and the original case index.
- `clients[].caseResults.failedCases[].caseIndex` (integer): Zero-based index of the failed case in the original Cases array.
- `clients[].caseResults.failedCases[].creditorReference` (string, nullable): Creditor reference from the failed case, if provided.
Helps consumers identify which specific case failed.
- `clients[].caseResults.failedCases[].errorType` (string, nullable): Machine-readable error type code for programmatic error handling.
Enables API consumers to handle different failure scenarios without parsing error messages.
            

<b>Possible values:</b><list type="bullet"><item><term>NoPartnerAvailable</term><description>No collection partner available for the debtor's jurisdiction.
The debtor is in a country/region where Debitura does not yet have collection partner coverage.
Consider resubmitting with debtors in supported jurisdictions.</description></item><item><term>ValidationError</term><description>The request failed field-level validation.
Check the ValidationErrors property for detailed field-specific errors.
Common causes: missing required fields, invalid formats, business rule violations.</description></item><item><term>DuplicateReference</term><description>The provided CreditorReference already exists for this creditor or is duplicated in the current request.
CreditorReference must be unique per creditor.</description></item><item><term>IdempotencyViolation</term><description>The client has already been created in a previous API call.
Cases are not created on repeated calls to maintain idempotency.
This is informational - the original operation already succeeded.</description></item><item><term>UnexpectedError</term><description>An unexpected system error occurred during case creation.
This is a catch-all for errors not covered by other types.
Contact Debitura support if this error persists.</description></item></list>
Null if the error type cannot be determined or is not applicable.
- `clients[].caseResults.failedCases[].errorMessage` (string, nullable): High-level error message explaining why the case creation failed.
- `clients[].caseResults.failedCases[].validationErrors` (object, nullable): Detailed field-level validation errors if the failure was due to validation.
Null if the failure was due to other reasons (e.g., no partner match).
- `clients[].caseResults.failedCases[].signingHandoff` (object): Partner-facing handoff metadata for a creditor's pending signing chain.
Returned on POST /cases responses (422 with pending-signing errors,
or 200 with AllowPendingContracts=true when signings remain).
            
Designed as an envelope so future fields (expiration, suggested email
copy, etc.) can be added without polluting the parent DTO.
- `clients[].caseResults.failedCases[].signingHandoff.combinedSigningUrl` (string, nullable): Single signing entry URL that walks the creditor through every
pending step (SDCA upgrade → PoA → JPA → KYC) on the Creditors app
and returns to the partner-supplied returnUrl when done.

```json
{
  "page": {
    "totalResults": 42,
    "pageSize": 25,
    "currentPage": 1,
    "responseCount": 42,
    "totalPages": 1
  },
  "summary": {
    "totalClients": 42,
    "attributedClients": 3,
    "onboardingComplete": 3,
    "onboardingPending": 3,
    "totalCases": 42
  },
  "clients": [
    {
      "externalTenantId": "string",
      "onboardingDone": true,
      "onboardingLinks": {
        "url": "https://app.debitura.com/…"
      },
      "client": {
        "id": "3f2b6c1e-8a4d-4b7f-9c2e-5d1a0b9e7f31",
        "companyName": "Muster GmbH",
        "officeEmail": "finance@example.com",
        "country": "Germany",
        "address": "Friedrichstraße 68",
        "city": "Berlin",
        "zipCode": "10115",
        "companyRegistrationNumber": "DE123456789"
      },
      "users": [
        {
          "id": {},
          "email": {},
          "firstName": {},
          "lastName": {}
        }
      ],
      "isAttributedClient": true,
      "dateLinked": "2026-10-01T14:05:00Z",
      "caseStats": {
        "casesTotal": 42,
        "casesClosed": 3,
        "earningsUsd": 1.5
      },
      "kycStatus": "NotRequired",
      "kycVerification": {
        "directorFullName": "Muster GmbH",
        "directorHomeAddress": "Friedrichstraße 68",
        "directorDateOfBirth": "2026-10-01",
        "dateCreated": "2026-10-01T14:05:00Z",
        "verificationStatus": "Processing",
        "verificationStatusUpdatedAt": "2026-10-01T14:05:00Z"
      },
      "caseResults": {
        "successfulCases": [
          {}
        ],
        "failedCases": [
          {}
        ]
      }
    }
  ]
}
```

### Response 400

Invalid request parameters

- `error` (string, nullable): Short human-readable error label (legacy field — preserved for backward compatibility).
- `message` (string, nullable): Human-readable error description (legacy field — preserved for backward compatibility).
- `businessErrors` (array of objects, nullable): Canonical structured error array. Consumers should migrate to reading this field.
- `businessErrors[].type` (string, nullable): The type of business error (e.g., "MissingDebtCollectionContract", "MissingPowerOfAttorney", "NoPartnerAvailable").
- `businessErrors[].message` (string, nullable): A human-readable description of the error.
- `businessErrors[].solutionUrl` (string, nullable): A URL where the user can resolve this <i>specific</i> error (e.g., sign a contract).
            

Partners who want a <b>single URL</b> that walks the user through every pending
signing in one chain — instead of forwarding one URL per
`BusinessErrorApiDTO` — should use
SigningHandoff's `CombinedSigningUrl`.
The two are complementary: `SolutionUrl` is granular per-error;
`CombinedSigningUrl` is the chain-walking alternative for signing-related errors.

```json
{
  "error": null,
  "message": "Payment plan agreed with the debtor.",
  "businessErrors": [
    {
      "type": "string",
      "message": "Payment plan agreed with the debtor.",
      "solutionUrl": "https://app.debitura.com/…"
    }
  ]
}
```

### Response 500

Internal server error

- `error` (string, nullable): Short human-readable error label (legacy field — preserved for backward compatibility).
- `message` (string, nullable): Human-readable error description (legacy field — preserved for backward compatibility).
- `businessErrors` (array of objects, nullable): Canonical structured error array. Consumers should migrate to reading this field.
- `businessErrors[].type` (string, nullable): The type of business error (e.g., "MissingDebtCollectionContract", "MissingPowerOfAttorney", "NoPartnerAvailable").
- `businessErrors[].message` (string, nullable): A human-readable description of the error.
- `businessErrors[].solutionUrl` (string, nullable): A URL where the user can resolve this <i>specific</i> error (e.g., sign a contract).
            

Partners who want a <b>single URL</b> that walks the user through every pending
signing in one chain — instead of forwarding one URL per
`BusinessErrorApiDTO` — should use
SigningHandoff's `CombinedSigningUrl`.
The two are complementary: `SolutionUrl` is granular per-error;
`CombinedSigningUrl` is the chain-walking alternative for signing-related errors.

```json
{
  "error": null,
  "message": "Payment plan agreed with the debtor.",
  "businessErrors": [
    {
      "type": "string",
      "message": "Payment plan agreed with the debtor.",
      "solutionUrl": "https://app.debitura.com/…"
    }
  ]
}
```

<a id="create-and-onboard-a-new-client"></a>

## 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
1. **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:** Without `Idempotency-Key`, `externalTenantId` only prevents a duplicate client/link;
   it does not make case-bearing retries safe or replay the original response. Exact response replay
   and case-safe retries require `Idempotency-Key`. Client/link lookups still re-check SDCA status,
   so an unkeyed call for an existing client that previously returned `201 Created` may flip to
   `202 Accepted` if Debitura releases a new SDCA version requiring re-signature.

2. **Existing Client - Needs Linking (409 Conflict)**
   Business conflicts use ConflictResponse.Type; keyed requests can additionally return
   IdempotencyKeyInProgress while the winning request is still running:

   **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=true` is forced on replay so cases land in `PendingContractSigning` rather than 422-failing on missing SDCA/PoA/KYC.
   - Returns 409 with OnboardingLinks.Url pointing to approval page

   **2b. ClientAlreadyLinkedToAnotherPartner** (Type: "ClientAlreadyLinkedToAnotherPartner")
   - 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

3. **Idempotency**
   - Without an Idempotency-Key, repeated calls with the same ExternalTenantId keep the existing
     business-key behaviour and return the current client status without duplicating the client or link
   - Optionally send an Idempotency-Key of up to 255 characters. The key is scoped to the authenticated
     referral partner and retained for 24 hours
   - The same key with the same effective request body replays the original terminal status and body,
     including approval-required 409 responses
   - Effective comparison follows this endpoint's execution rules. For one user,
     IsOnboardingUser=false and true are equivalent because the user is always selected for onboarding.
     Omitted and empty Cases/ClaimLines are equivalent. Within Cases, AllowPendingContracts
     and AssignedUserEmail do not change referral-onboarding execution;
     unsafe ReturnUrl values are dropped; valid debtor Type casing is normalized; ContactPerson is
     ignored for Private debtors; and State is ignored when StateAlpha2 is supplied.
   - The same key with a different effective body returns 422 with businessErrors[0].type = IdempotencyConflict;
     a retry while the first request is still running returns 409 with
     businessErrors[0].type = IdempotencyKeyInProgress and Retry-After: 2
   - Field-validation 400 responses and failures before any durable effect do not consume the key.
     A failure after client, link, approval-request, or case work starts is sealed and replayed to prevent duplicates

4. **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** - Business conflicts or keyed-request contention:
  - ConflictResponse.Type = "ClientExistsNeedsLinking" - Client exists, needs approval link (if approved, IsAttributedClient=false)
  - ConflictResponse.Type = "ClientAlreadyLinkedToAnotherPartner" - Client already linked to different partner (cannot proceed)
  - ConflictResponse.Type = "PartnerNotAcceptingReferrals" - The referral partner is paused or closed and takes no new clients; existing clients are unaffected
  - businessErrors[0].type = "IdempotencyKeyInProgress" - Another request with the same partner, key, and effective body is still running; retry after the Retry-After delay
- **422 Unprocessable Entity** - Business rule violation, including businessErrors[0].type = "IdempotencyConflict" when the same key is reused with a different effective body
- **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:
1. `amountToRecover` plus a single `dueDate`
2. `amountToRecover` plus the cumulative `amountToRecoverOver6/12/24Months` buckets
3. `claimLines[]` — 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" }
]
```

- `amount` is the **outstanding balance** on that invoice, already net of payments and credit notes.
- We derive `amountToRecover` and all three age buckets from the lines, so send `claimLines` **instead of** `amountToRecover` and 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 explicit `dueDate` is 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`.
- `claimLines` is 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)

### Headers

- `Idempotency-Key` (string): Optional non-empty, non-whitespace idempotency key (max 255 characters) for safely retrying this request. If a previous request used the same key with the same effective request body, the original terminal response is replayed verbatim. Reusing the key for a different effective request returns 422 with `businessErrors[0].type: "IdempotencyConflict"`. Field-level 400 validation errors are not stored, so you may fix the request and retry with the same key. An approval-required 409 remains the stored response even after the client later approves; use the client lookup or webhooks for current state.
  Max 255 characters.

### Request body (application/json)

- `externalTenantId` (string, required): 
- `client` (object, required): 
- `client.name` (string, required): 
- `client.registrationNumber` (string, nullable): 
- `client.address` (string, nullable): 
  Max 500 characters.
- `client.zipCode` (string, nullable): 
  Max 20 characters.
- `client.city` (string, nullable): 
  Max 100 characters.
- `client.state` (string, nullable): 
  Max 100 characters.
- `client.country` (string, required): 
- `client.supportEmail` (string, required): 
  Email address.
- `client.supportPhone` (string, nullable): 
- `users` (array of objects, required): 
- `users[].name` (string, required): 
- `users[].email` (string, required): 
  Email address.
- `users[].isOnboardingUser` (boolean): Marks this user as the one going through onboarding.
Defaults to false. Exactly ONE user must have this set to true.
- `cases` (array of objects, nullable): Optional: Cases to create alongside the client.
If provided, cases will be created with PendingContractSigning status.
The onboarding URL will guide the client through contract signing for all required PoAs.
Supports multi-invoice age bucket pricing fields (AmountToRecoverOver6Months, AmountToRecoverOver12Months, AmountToRecoverOver24Months).
- `cases[].currencyCode` (string, required, nullable): 
- `cases[].date` (datetime): 
- `cases[].dueDate` (datetime, nullable): 
- `cases[].comments` (string, nullable): Optional comments about the case, e.g. payment history or communication context.
  Max 4000 characters.
- `cases[].claimDescription` (string, nullable): Client provided description of the claim
  Max 4000 characters.
- `cases[].creditorReference` (string, nullable): 
  Max 50 characters.
- `cases[].debtor` (object): V1 Debtor DTO for external partner APIs.
The debtor is the party that owes the debt.
- `cases[].debtor.type` (string, required): Debtor type. Valid values: "Company" or "Private" (case-insensitive)
- `cases[].debtor.name` (string, required): Debtor name (company name or person's full name)
- `cases[].debtor.contactPerson` (string, nullable): Contact person at the company (required for companies, not used for persons)
- `cases[].debtor.companyRegistrationNumber` (string, nullable): Company registration number (VAT number, CVR, org number, etc.)
- `cases[].debtor.address` (string, nullable): Street address
- `cases[].debtor.zipCode` (string, nullable): Postal/ZIP code
- `cases[].debtor.city` (string, nullable): City name
- `cases[].debtor.state` (string, nullable): State/region/province name
- `cases[].debtor.stateAlpha2` (string, nullable): US state: two-letter code (e.g., "CA"), ISO 3166-2 format (e.g., "US-CA"), or full name (e.g., "California")
- `cases[].debtor.countryAlpha2` (string, nullable): Country code (ISO 3166-1 alpha-2 format)
- `cases[].debtor.country` (string, nullable): Country name
- `cases[].debtor.email` (string, nullable): Email address for debtor contact
- `cases[].debtor.phone` (string, nullable): Phone number (include country code)
- `cases[].creditorDivisionId` (uuid, nullable): 
- `cases[].amountToRecover` (number): The TOTAL amount to recover for this case.
This represents the full principal amount across all invoices (if multiple invoices are bundled).
            
For multi-invoice cases with different ages, you can optionally provide age breakdown fields
(AmountToRecoverOver12Months and AmountToRecoverOver24Months) to enable blended age-based pricing.
            
If age breakdown fields are omitted, age uplift will be calculated from the invoice due date (single-invoice pricing).
            
Required unless you send ClaimLines, in which case this must be omitted or 0 — the server
derives the total by summing the outstanding balance of every claim line. Sending both a
non-zero AmountToRecover and ClaimLines is rejected, because the two would disagree.
- `cases[].amountToRecoverOver6Months` (number, nullable): OPTIONAL - MULTI-INVOICE AGE BUCKET PRICING (PRICING ZONE 180-DAY THRESHOLD)
            
The portion of AmountToRecover that is more than 6 months (180 days) overdue.
This includes amounts that are 12+ and 24+ months overdue.
            
This field is optional and can only be provided alongside AmountToRecoverOver12Months
and AmountToRecoverOver24Months. It enables precise pricing tier selection based on
the 180-day threshold. When omitted, the system falls back to deriving the threshold
from AmountToRecoverOver12Months.
            
Validation rules:
- Must be ≤ AmountToRecover
- Must be ≥ AmountToRecoverOver12Months
- `cases[].amountToRecoverOver12Months` (number, nullable): OPTIONAL - MULTI-INVOICE AGE BUCKET PRICING
            
The portion of AmountToRecover that is more than 12 months overdue.
This includes amounts that are 24+ months overdue.
            
If provided, AmountToRecoverOver24Months must also be provided.
Both fields must be provided together or both omitted.
            
Used to calculate blended age uplift for multi-invoice cases:
- Amount under 12 months = AmountToRecover - AmountToRecoverOver12Months
- Amount 12-24 months = AmountToRecoverOver12Months - AmountToRecoverOver24Months
- Amount over 24 months = AmountToRecoverOver24Months
            
Blended uplift formula: ((A12-A24)×10 + A24×20) / AmountToRecover
where A12 = AmountToRecoverOver12Months, A24 = AmountToRecoverOver24Months
            
Validation rules:
- Must be ≤ AmountToRecover
- Must be ≥ AmountToRecoverOver24Months
- `cases[].amountToRecoverOver24Months` (number, nullable): OPTIONAL - MULTI-INVOICE AGE BUCKET PRICING
            
The portion of AmountToRecover that is more than 24 months overdue.
            
If provided, AmountToRecoverOver12Months must also be provided.
Both fields must be provided together or both omitted.
            
Used to calculate blended age uplift for multi-invoice cases.
See AmountToRecoverOver12Months for full details on the calculation.
            
Validation rules:
- Must be ≤ AmountToRecoverOver12Months
- Must be ≤ AmountToRecover
- `cases[].claimLines` (array of objects, nullable): OPTIONAL - the unpaid invoices making up this claim, one line per invoice, each carrying its
own outstanding balance and payment deadline.
            
When supplied, the server derives AmountToRecover and all three cumulative age buckets from
these lines, so send them instead of — never alongside — AmountToRecover and the
AmountToRecoverOver6/12/24Months fields. Supplying both is rejected with a 400.
            
Use this whenever the debtor has already part-paid the claim: the buckets are then computed
on the same outstanding balances the total is computed on, so the age profile stays honest.
Maximum 1000 lines. When DueDate is omitted on the case, it is derived as the oldest line
due date; an explicit DueDate is honoured.
            
Claim lines are a pricing input only — they are not stored and are never shown to the
collecting partner.
- `cases[].claimLines[].dueDate` (datetime, required, nullable): Payment deadline of this invoice. Provide date only without time component.
Must be on or after 2000-01-01 and must not be in the future.
- `cases[].claimLines[].amount` (number, required): The outstanding balance on this invoice in the case currency — what the debtor still owes on it,
already net of any payments the debtor has made and net of any credit notes issued against it.
This is not the invoice's original face value.
Must be greater than zero with at most 2 decimal places; omit invoices that are fully settled.
- `cases[].claimLines[].reference` (string, nullable): Optional invoice number, used for validation and duplicate-line detection. Starter retains it with the original-line case snapshot, visible through existing case permissions; Full Integration does not retain that snapshot.
- `cases[].allowPendingContracts` (boolean): When true, cases with unsigned contracts (SDCA/POA) are accepted in 'PendingContractSigning'
status instead of being rejected with 422. The case transitions automatically once contracts are signed.
Default: false (unsigned contracts return 422).
- `cases[].isTest` (boolean): When true, creates a test case that IS persisted to the database but marked as test data.
Test cases are excluded from production metrics and can be easily filtered or deleted.
Use this for integration testing and development.
- `cases[].tag` (string, nullable): Optional tag for scoped test data grouping (e.g. "suite-run-{uuid}").
Use this to group test cases created by a single CI pipeline run so they can be
bulk-deleted via DELETE /test/cases?tag={tag} without affecting parallel runs.
Only meaningful when IsTest is true. Max 100 characters.
  Max 100 characters.
- `cases[].assignedUserEmail` (string, nullable): Optional: Email address of the creditor team member to assign as the case owner.
When provided, email notifications for this case will be sent only to this user
instead of all team members.
Must correspond to an active member of your team.
  Max 320 characters; Email address.
- `cases[].returnUrl` (string, nullable): Optional: URL the creditor user should land on after completing any
pending signing chain (SDCA upgrade / PoA / JPA / KYC) on the
Debitura Creditors app. Embedded, URL-encoded, into
`BusinessErrorResponseApiDTO.SigningHandoff.CombinedSigningUrl`
(on 422 with pending signings) and
`InvoiceDto.SigningHandoff.CombinedSigningUrl` (on 200 when
`AllowPendingContracts=true` with signings remaining).
            
Must be an absolute http(s) URL. Values that fail validation
(relative URLs, non-http schemes, header-injection characters) are
silently dropped — the combined URL is still emitted but without
the returnUrl query parameter, and the Creditors app falls back to
its own safe in-app default landing.
            
Additive. Existing integrations
that omit this field see the same behaviour as before.
  Max 2048 characters.

```json
{
  "externalTenantId": "tenant-12345",
  "client": {
    "name": "Acme Corp",
    "registrationNumber": "12345678",
    "address": "123 Business Street",
    "zipCode": "1000",
    "city": "Lisbon",
    "state": "Lisbon",
    "country": "Portugal",
    "supportEmail": "billing@acme-corp.com",
    "supportPhone": "+351 123 456 789"
  },
  "users": [
    {
      "name": "John Doe",
      "email": "john.doe@acme-corp.com",
      "isOnboardingUser": true
    }
  ],
  "cases": [
    {
      "currencyCode": "EUR",
      "amountToRecover": 4000,
      "date": "2026-03-01",
      "dueDate": "2026-03-09",
      "claimDescription": "Custom mobile app development services",
      "comments": "Outstanding invoice INV 2024 00789 for custom mobile app development delivered 15 Nov 2024; payment 60 days overdue despite two reminders.",
      "creditorReference": "INV‑2024‑00789",
      "isTest": false,
      "debtor": {
        "type": "Company",
        "name": "Acme Corp",
        "contactPerson": "John Doe",
        "companyRegistrationNumber": "12345678",
        "address": "123 Business Street",
        "zipCode": "1000",
        "city": "Lisbon",
        "state": "Lisbon",
        "countryAlpha2": "PT",
        "email": "billing@acme‑corp.com",
        "phone": "+351 123 456 789"
      }
    }
  ]
}
```

### Response 201

Client created and fully onboarded (terms signed)

- `externalTenantId` (string, nullable): 
- `onboardingDone` (boolean): 
- `onboardingLinks` (object): 
- `onboardingLinks.url` (string, nullable): 
- `client` (object): 
- `client.id` (uuid): 
- `client.companyName` (string, nullable): 
- `client.officeEmail` (string, nullable): 
- `client.country` (string, nullable): 
- `client.address` (string, nullable): 
- `client.city` (string, nullable): 
- `client.zipCode` (string, nullable): 
- `client.companyRegistrationNumber` (string, nullable): 
- `users` (array of objects, nullable): 
- `users[].id` (integer): 
- `users[].email` (string, nullable): 
- `users[].firstName` (string, nullable): 
- `users[].lastName` (string, nullable): 
- `isAttributedClient` (boolean): 
- `dateLinked` (datetime): 
- `caseStats` (object): 
- `caseStats.casesTotal` (integer): 
- `caseStats.casesClosed` (integer): 
- `caseStats.earningsUsd` (number): 
- `kycStatus` (enum): KYC (Know Your Customer) verification status for a client linked to a referral partner.
Captures three distinct states that a simple boolean cannot express.
Sent as snake_case string values: "not_required", "pending", "verified".
  Values: `NotRequired`, `Pending`, `Verified`.
- `kycVerification` (object): 
- `kycVerification.directorFullName` (string, nullable): 
- `kycVerification.directorHomeAddress` (string, nullable): 
- `kycVerification.directorDateOfBirth` (date): 
- `kycVerification.dateCreated` (datetime): 
- `kycVerification.verificationStatus` (enum, nullable): Partner/staff-set review status (Processing/Completed) for this submission. Null = not yet
reviewed. Note: distinct from the sibling `ClientResponse.KycStatus` field, which
describes whether KYC data has been submitted at all.
  Values: `Processing`, `Completed`, `null`.
- `kycVerification.verificationStatusUpdatedAt` (datetime, nullable): When VerificationStatus was last set. Null until set.
- `caseResults` (object): Result of creating multiple cases during client creation.
Groups successful and failed case creation attempts.
- `caseResults.successfulCases` (array of objects, nullable): Cases that were created successfully.
Each element contains the full case details.
- `caseResults.successfulCases[].id` (uuid): 
- `caseResults.successfulCases[].dateCreated` (datetime): 
- `caseResults.successfulCases[].dateUpdated` (datetime, nullable): 
- `caseResults.successfulCases[].reference` (string, nullable): 
- `caseResults.successfulCases[].creditorReference` (string, nullable): 
- `caseResults.successfulCases[].creditorComments` (string, nullable): 
- `caseResults.successfulCases[].claimDescription` (string, nullable): 
- `caseResults.successfulCases[].grossAmount` (number): 
- `caseResults.successfulCases[].remainder` (number): 
- `caseResults.successfulCases[].interestFees` (number): 
- `caseResults.successfulCases[].reminderFees` (number): 
- `caseResults.successfulCases[].collectionFees` (number): 
- `caseResults.successfulCases[].totalAddedFees` (number): 
- `caseResults.successfulCases[].currency` (string, nullable): 
- `caseResults.successfulCases[].isTestCase` (boolean): 
- `caseResults.successfulCases[].lifecycle` (string, nullable): 
- `caseResults.successfulCases[].dueDate` (datetime): 
- `caseResults.successfulCases[].date` (datetime): 
- `caseResults.successfulCases[].dateFinished` (datetime, nullable): 
- `caseResults.successfulCases[].dateCollectionStarted` (datetime, nullable): 
- `caseResults.successfulCases[].closeCode` (string, nullable): 
- `caseResults.successfulCases[].currentEngagementPhase` (string, nullable): The current phase of the case's engagement: "Pre-legal", "Legal", or "Enforcement".
A different axis from Lifecycle/CloseCode — an Active case can be
in any of the three phases.
            
Null means "no active engagement" (e.g. lead / quoting / pre-contract-signing / unassigned, or
a data-consistency gap) — this is a distinct third state, NOT a synonym for Pre-legal. Most
cases legitimately read Pre-legal; phase only leaves Pre-legal on legal/enforcement quote flows.
            
Not guaranteed to be monotonic: an admin correction can move phase backwards (e.g. Legal back
to Pre-legal).
            
Persists after case closure — reflects the case's last-known engagement phase, not the current
Lifecycle. Note: this is a different field from a lead quote's own offered phase (the phase a
partner's quote proposes to work the case at, if this case ever went through a quote flow) —
this field is the case-level phase of its actual engagement, not a quote's terms.
- `caseResults.successfulCases[].claimType` (string, nullable): The type of claim for this case (e.g. "Unpaid Invoice", "Loan Repayment", "Breach of Contract").
Null if not set.
- `caseResults.successfulCases[].creditorDivisionId` (uuid, nullable): 
- `caseResults.successfulCases[].debtor` (object): V1 Debtor DTO for external partner APIs.
The debtor is the party that owes the debt.
- `caseResults.successfulCases[].debtor.type` (string, required): Debtor type. Valid values: "Company" or "Private" (case-insensitive)
- `caseResults.successfulCases[].debtor.name` (string, required): Debtor name (company name or person's full name)
- `caseResults.successfulCases[].debtor.contactPerson` (string, nullable): Contact person at the company (required for companies, not used for persons)
- `caseResults.successfulCases[].debtor.companyRegistrationNumber` (string, nullable): Company registration number (VAT number, CVR, org number, etc.)
- `caseResults.successfulCases[].debtor.address` (string, nullable): Street address
- `caseResults.successfulCases[].debtor.zipCode` (string, nullable): Postal/ZIP code
- `caseResults.successfulCases[].debtor.city` (string, nullable): City name
- `caseResults.successfulCases[].debtor.state` (string, nullable): State/region/province name
- `caseResults.successfulCases[].debtor.stateAlpha2` (string, nullable): US state: two-letter code (e.g., "CA"), ISO 3166-2 format (e.g., "US-CA"), or full name (e.g., "California")
- `caseResults.successfulCases[].debtor.countryAlpha2` (string, nullable): Country code (ISO 3166-1 alpha-2 format)
- `caseResults.successfulCases[].debtor.country` (string, nullable): Country name
- `caseResults.successfulCases[].debtor.email` (string, nullable): Email address for debtor contact
- `caseResults.successfulCases[].debtor.phone` (string, nullable): Phone number (include country code)
- `caseResults.successfulCases[].collectionPartner` (object): V1 Collection Partner DTO for external partner APIs
- `caseResults.successfulCases[].collectionPartner.name` (string, nullable): 
- `caseResults.successfulCases[].collectionPartner.officeEmail` (string, nullable): 
- `caseResults.successfulCases[].collectionPartner.officePhone` (string, nullable): 
- `caseResults.successfulCases[].collectionPartner.publicSite` (string, nullable): 
- `caseResults.successfulCases[].collectionPartner.surveyCadenceMode` (enum, deprecated): Deprecated: kept as a number and never removed, but not extended. Survey-generation cadence: 0 = Standard
(rolling monthly survey), 1 = DecisionPointOnly (no rolling surveys).
  Values: `0`, `1`.
- `caseResults.successfulCases[].creditor` (object): Creditor (client) information for external partner APIs.
Represents the party that the debtor owes money to.
- `caseResults.successfulCases[].creditor.id` (uuid): Unique identifier for the creditor
- `caseResults.successfulCases[].creditor.companyName` (string, nullable): Company name of the creditor
- `caseResults.successfulCases[].creditor.companyRegistrationNumber` (string, nullable): Company registration number (CVR, VAT number, etc.)
- `caseResults.successfulCases[].creditor.officeEmail` (string, nullable): Primary office email address
- `caseResults.successfulCases[].creditor.officePhone` (string, nullable): Primary office phone number
- `caseResults.successfulCases[].creditor.address` (string, nullable): Street address
- `caseResults.successfulCases[].creditor.city` (string, nullable): City
- `caseResults.successfulCases[].creditor.zipCode` (string, nullable): Postal/ZIP code
- `caseResults.successfulCases[].creditor.state` (string, nullable): State or region (if applicable)
- `caseResults.successfulCases[].creditor.country` (string, nullable): Country name
- `caseResults.successfulCases[].creditor.division` (object): Creditor division information for external partner APIs.
Represents a specific division or department within a creditor organization.
- `caseResults.successfulCases[].creditor.division.id` (uuid): Unique identifier for the division
- `caseResults.successfulCases[].creditor.division.name` (string, nullable): Name of the division
- `caseResults.successfulCases[].bankAccount` (object): Bank account information for partner API.
Full details provided as partners need this to:
1. Provide payment instructions to debtors (when debtor pays client directly)
2. Execute payouts to clients (when partner receives payment and pays out remainder)
- `caseResults.successfulCases[].bankAccount.id` (integer): Bank account identifier
- `caseResults.successfulCases[].bankAccount.label` (string, nullable): User-friendly label (e.g., "Main EUR Account")
- `caseResults.successfulCases[].bankAccount.scheme` (string, nullable): Account scheme: IBAN, SWIFT, or LOCAL
- `caseResults.successfulCases[].bankAccount.currencyCode` (string, nullable): Currency code (ISO 4217)
- `caseResults.successfulCases[].bankAccount.bankCountryCode` (string, nullable): Bank country code (ISO Alpha-2)
- `caseResults.successfulCases[].bankAccount.accountHolderName` (string, nullable): Account holder name (beneficiary)
- `caseResults.successfulCases[].bankAccount.iban` (string, nullable): IBAN (for IBAN scheme accounts)
- `caseResults.successfulCases[].bankAccount.bic` (string, nullable): BIC/SWIFT code (for IBAN and SWIFT scheme accounts)
- `caseResults.successfulCases[].bankAccount.accountNumber` (string, nullable): Account number (for SWIFT and LOCAL scheme accounts)
- `caseResults.successfulCases[].bankAccount.localIdentifier` (string, nullable): Local identifier (for LOCAL scheme accounts, e.g., sort code + account number)
- `caseResults.successfulCases[].bankAccount.localIdentifierType` (string, nullable): Type of local identifier (e.g., "Sort Code", "Routing Number")
- `caseResults.successfulCases[].bankAccount.bankName` (string, nullable): Bank name (optional)
- `caseResults.successfulCases[].bankAccount.bankAddress` (string, nullable): Bank address (optional)
- `caseResults.successfulCases[].bankAccount.bankCity` (string, nullable): Bank city (optional)
- `caseResults.successfulCases[].bankAccount.bankZipCode` (string, nullable): Bank zip/postal code (optional)
- `caseResults.successfulCases[].bankAccount.bankState` (string, nullable): Bank state/region (optional)
- `caseResults.successfulCases[].blendedAgeUpliftPoints` (number, nullable): MULTI-INVOICE AGE BUCKET PRICING
Calculated blended age uplift percentage points (0-20) for multi-invoice cases.
Shows the additional fee percentage added due to invoice age.
Formula: ((A12-A24)×10 + A24×20) / Total Principal
Null for single-invoice cases (age uplift is calculated from due date instead).
- `caseResults.successfulCases[].preLegalSuccessFee` (number, nullable): PRE-LEGAL SUCCESS FEE
The total pre-legal success fee percentage for this case.
Includes base fee + age-based uplift (blended or single-invoice).
Null if pricing has not been calculated yet or if case is not in pre-legal phase.
Example: 20.5 represents 20.5% success fee.
- `caseResults.successfulCases[].solutionUrl` (string, nullable, deprecated): When the case is created with allowPendingContracts=true and required contracts are unsigned,
this URL points to the signing page. Null when contracts are already signed or not applicable.
- `caseResults.successfulCases[].signingHandoff` (object): Partner-facing handoff metadata for a creditor's pending signing chain.
Returned on POST /cases responses (422 with pending-signing errors,
or 200 with AllowPendingContracts=true when signings remain).
            
Designed as an envelope so future fields (expiration, suggested email
copy, etc.) can be added without polluting the parent DTO.
- `caseResults.successfulCases[].signingHandoff.combinedSigningUrl` (string, nullable): Single signing entry URL that walks the creditor through every
pending step (SDCA upgrade → PoA → JPA → KYC) on the Creditors app
and returns to the partner-supplied returnUrl when done.
- `caseResults.successfulCases[].exclusivePeriodEndDate` (datetime, nullable): The date the exclusive collection period ends (or ended).
Null if no collection period has been created for this case (e.g. custom-terms cases).
Use GET /cases/{id}/exclusive-period for the full chain including extensions.
- `caseResults.successfulCases[].disputeStatus` (string, nullable): Whether the claim is disputed by the debtor.
One of: "Yes, the claim is disputed", "No, the claim is not disputed", or "Don't Know".
Null when the dispute status has not been set on the case.
- `caseResults.successfulCases[].validation` (object): Stable v1 validation summary used by ordinary and list mappings.
- `caseResults.successfulCases[].validation.needsInfo` (boolean): 
- `caseResults.successfulCases[].assignedUser` (object): Represents the creditor team member assigned to a case.
- `caseResults.successfulCases[].assignedUser.email` (string, nullable): The assigned user's email address.
- `caseResults.successfulCases[].assignedUser.name` (string, nullable): The assigned user's full name.
- `caseResults.successfulCases[].allocationOutstanding` (object): Outstanding amount per bucket on the case: each bucket's total minus the payments allocated to it.
- `caseResults.successfulCases[].allocationOutstanding.principal` (number): 
- `caseResults.successfulCases[].allocationOutstanding.interest` (number): 
- `caseResults.successfulCases[].allocationOutstanding.reminderFees` (number): 
- `caseResults.successfulCases[].allocationOutstanding.collectionFees` (number): 
- `caseResults.failedCases` (array of objects, nullable): Cases that failed during creation.
Each element contains error details and the original case index.
- `caseResults.failedCases[].caseIndex` (integer): Zero-based index of the failed case in the original Cases array.
- `caseResults.failedCases[].creditorReference` (string, nullable): Creditor reference from the failed case, if provided.
Helps consumers identify which specific case failed.
- `caseResults.failedCases[].errorType` (string, nullable): Machine-readable error type code for programmatic error handling.
Enables API consumers to handle different failure scenarios without parsing error messages.
            

<b>Possible values:</b><list type="bullet"><item><term>NoPartnerAvailable</term><description>No collection partner available for the debtor's jurisdiction.
The debtor is in a country/region where Debitura does not yet have collection partner coverage.
Consider resubmitting with debtors in supported jurisdictions.</description></item><item><term>ValidationError</term><description>The request failed field-level validation.
Check the ValidationErrors property for detailed field-specific errors.
Common causes: missing required fields, invalid formats, business rule violations.</description></item><item><term>DuplicateReference</term><description>The provided CreditorReference already exists for this creditor or is duplicated in the current request.
CreditorReference must be unique per creditor.</description></item><item><term>IdempotencyViolation</term><description>The client has already been created in a previous API call.
Cases are not created on repeated calls to maintain idempotency.
This is informational - the original operation already succeeded.</description></item><item><term>UnexpectedError</term><description>An unexpected system error occurred during case creation.
This is a catch-all for errors not covered by other types.
Contact Debitura support if this error persists.</description></item></list>
Null if the error type cannot be determined or is not applicable.
- `caseResults.failedCases[].errorMessage` (string, nullable): High-level error message explaining why the case creation failed.
- `caseResults.failedCases[].validationErrors` (object, nullable): Detailed field-level validation errors if the failure was due to validation.
Null if the failure was due to other reasons (e.g., no partner match).
- `caseResults.failedCases[].signingHandoff` (object): Partner-facing handoff metadata for a creditor's pending signing chain.
Returned on POST /cases responses (422 with pending-signing errors,
or 200 with AllowPendingContracts=true when signings remain).
            
Designed as an envelope so future fields (expiration, suggested email
copy, etc.) can be added without polluting the parent DTO.
- `caseResults.failedCases[].signingHandoff.combinedSigningUrl` (string, nullable): Single signing entry URL that walks the creditor through every
pending step (SDCA upgrade → PoA → JPA → KYC) on the Creditors app
and returns to the partner-supplied returnUrl when done.

```json
{
  "externalTenantId": "string",
  "onboardingDone": true,
  "onboardingLinks": {
    "url": "https://app.debitura.com/…"
  },
  "client": {
    "id": "3f2b6c1e-8a4d-4b7f-9c2e-5d1a0b9e7f31",
    "companyName": "Muster GmbH",
    "officeEmail": "finance@example.com",
    "country": "Germany",
    "address": "Friedrichstraße 68",
    "city": "Berlin",
    "zipCode": "10115",
    "companyRegistrationNumber": "DE123456789"
  },
  "users": [
    {
      "id": 3,
      "email": "finance@example.com",
      "firstName": "Anna",
      "lastName": "Schmidt"
    }
  ],
  "isAttributedClient": true,
  "dateLinked": "2026-10-01T14:05:00Z",
  "caseStats": {
    "casesTotal": 42,
    "casesClosed": 3,
    "earningsUsd": 1.5
  },
  "kycStatus": "NotRequired",
  "kycVerification": {
    "directorFullName": "Muster GmbH",
    "directorHomeAddress": "Friedrichstraße 68",
    "directorDateOfBirth": "2026-10-01",
    "dateCreated": "2026-10-01T14:05:00Z",
    "verificationStatus": "Processing",
    "verificationStatusUpdatedAt": "2026-10-01T14:05:00Z"
  },
  "caseResults": {
    "successfulCases": [
      {
        "id": "3f2b6c1e-8a4d-4b7f-9c2e-5d1a0b9e7f31",
        "dateCreated": "2026-10-01T14:05:00Z",
        "dateUpdated": "2026-10-01T14:05:00Z",
        "reference": "INV-2026-0042",
        "creditorReference": "INV-2026-0042",
        "creditorComments": "Payment plan agreed with the debtor.",
        "claimDescription": "string",
        "grossAmount": 2500,
        "remainder": 1.5,
        "interestFees": 2500,
        "reminderFees": 2500,
        "collectionFees": 2500,
        "totalAddedFees": 2500,
        "currency": "EUR",
        "isTestCase": true,
        "lifecycle": "string",
        "dueDate": "2026-10-01T14:05:00Z",
        "date": "2026-10-01T14:05:00Z",
        "dateFinished": "2026-10-01T14:05:00Z",
        "dateCollectionStarted": "2026-10-01T14:05:00Z",
        "closeCode": "string",
        "currentEngagementPhase": "string",
        "claimType": "string",
        "creditorDivisionId": "3f2b6c1e-8a4d-4b7f-9c2e-5d1a0b9e7f31",
        "debtor": {
          "type": "Company",
          "name": "Pacific Trading LLC",
          "contactPerson": "John Smith",
          "companyRegistrationNumber": "47-1234567",
          "address": "123 Market Street, Suite 400",
          "zipCode": "94105",
          "city": "San Francisco",
          "state": "California",
          "stateAlpha2": "CA",
          "countryAlpha2": "US",
          "country": "United States",
          "email": "accounts@pacifictrading.com",
          "phone": "+1 415 555 0123"
        },
        "collectionPartner": {
          "name": {},
          "officeEmail": {},
          "officePhone": {},
          "publicSite": {},
          "surveyCadenceMode": {}
        },
        "creditor": {
          "id": {},
          "companyName": {},
          "companyRegistrationNumber": {},
          "officeEmail": {},
          "officePhone": {},
          "address": {},
          "city": {},
          "zipCode": {},
          "state": {},
          "country": {},
          "division": {}
        },
        "bankAccount": {
          "id": {},
          "label": {},
          "scheme": {},
          "currencyCode": {},
          "bankCountryCode": {},
          "accountHolderName": {},
          "iban": {},
          "bic": {},
          "accountNumber": {},
          "localIdentifier": {},
          "localIdentifierType": {},
          "bankName": {},
          "bankAddress": {},
          "bankCity": {},
          "bankZipCode": {},
          "bankState": {}
        },
        "blendedAgeUpliftPoints": 1.5,
        "preLegalSuccessFee": 2500,
        "solutionUrl": "https://app.debitura.com/…",
        "signingHandoff": {
          "combinedSigningUrl": {}
        },
        "exclusivePeriodEndDate": "2026-10-01T14:05:00Z",
        "disputeStatus": "string",
        "validation": {
          "needsInfo": {}
        },
        "assignedUser": {
          "email": {},
          "name": {}
        },
        "allocationOutstanding": {
          "principal": {},
          "interest": {},
          "reminderFees": {},
          "collectionFees": {}
        }
      }
    ],
    "failedCases": [
      {
        "caseIndex": 3,
        "creditorReference": "INV-2026-0042",
        "errorType": null,
        "errorMessage": null,
        "validationErrors": {},
        "signingHandoff": {
          "combinedSigningUrl": {}
        }
      }
    ]
  }
}
```

### Response 202

Client created but onboarding incomplete (use OnboardingLinks.Url to complete)

- `externalTenantId` (string, nullable): 
- `onboardingDone` (boolean): 
- `onboardingLinks` (object): 
- `onboardingLinks.url` (string, nullable): 
- `client` (object): 
- `client.id` (uuid): 
- `client.companyName` (string, nullable): 
- `client.officeEmail` (string, nullable): 
- `client.country` (string, nullable): 
- `client.address` (string, nullable): 
- `client.city` (string, nullable): 
- `client.zipCode` (string, nullable): 
- `client.companyRegistrationNumber` (string, nullable): 
- `users` (array of objects, nullable): 
- `users[].id` (integer): 
- `users[].email` (string, nullable): 
- `users[].firstName` (string, nullable): 
- `users[].lastName` (string, nullable): 
- `isAttributedClient` (boolean): 
- `dateLinked` (datetime): 
- `caseStats` (object): 
- `caseStats.casesTotal` (integer): 
- `caseStats.casesClosed` (integer): 
- `caseStats.earningsUsd` (number): 
- `kycStatus` (enum): KYC (Know Your Customer) verification status for a client linked to a referral partner.
Captures three distinct states that a simple boolean cannot express.
Sent as snake_case string values: "not_required", "pending", "verified".
  Values: `NotRequired`, `Pending`, `Verified`.
- `kycVerification` (object): 
- `kycVerification.directorFullName` (string, nullable): 
- `kycVerification.directorHomeAddress` (string, nullable): 
- `kycVerification.directorDateOfBirth` (date): 
- `kycVerification.dateCreated` (datetime): 
- `kycVerification.verificationStatus` (enum, nullable): Partner/staff-set review status (Processing/Completed) for this submission. Null = not yet
reviewed. Note: distinct from the sibling `ClientResponse.KycStatus` field, which
describes whether KYC data has been submitted at all.
  Values: `Processing`, `Completed`, `null`.
- `kycVerification.verificationStatusUpdatedAt` (datetime, nullable): When VerificationStatus was last set. Null until set.
- `caseResults` (object): Result of creating multiple cases during client creation.
Groups successful and failed case creation attempts.
- `caseResults.successfulCases` (array of objects, nullable): Cases that were created successfully.
Each element contains the full case details.
- `caseResults.successfulCases[].id` (uuid): 
- `caseResults.successfulCases[].dateCreated` (datetime): 
- `caseResults.successfulCases[].dateUpdated` (datetime, nullable): 
- `caseResults.successfulCases[].reference` (string, nullable): 
- `caseResults.successfulCases[].creditorReference` (string, nullable): 
- `caseResults.successfulCases[].creditorComments` (string, nullable): 
- `caseResults.successfulCases[].claimDescription` (string, nullable): 
- `caseResults.successfulCases[].grossAmount` (number): 
- `caseResults.successfulCases[].remainder` (number): 
- `caseResults.successfulCases[].interestFees` (number): 
- `caseResults.successfulCases[].reminderFees` (number): 
- `caseResults.successfulCases[].collectionFees` (number): 
- `caseResults.successfulCases[].totalAddedFees` (number): 
- `caseResults.successfulCases[].currency` (string, nullable): 
- `caseResults.successfulCases[].isTestCase` (boolean): 
- `caseResults.successfulCases[].lifecycle` (string, nullable): 
- `caseResults.successfulCases[].dueDate` (datetime): 
- `caseResults.successfulCases[].date` (datetime): 
- `caseResults.successfulCases[].dateFinished` (datetime, nullable): 
- `caseResults.successfulCases[].dateCollectionStarted` (datetime, nullable): 
- `caseResults.successfulCases[].closeCode` (string, nullable): 
- `caseResults.successfulCases[].currentEngagementPhase` (string, nullable): The current phase of the case's engagement: "Pre-legal", "Legal", or "Enforcement".
A different axis from Lifecycle/CloseCode — an Active case can be
in any of the three phases.
            
Null means "no active engagement" (e.g. lead / quoting / pre-contract-signing / unassigned, or
a data-consistency gap) — this is a distinct third state, NOT a synonym for Pre-legal. Most
cases legitimately read Pre-legal; phase only leaves Pre-legal on legal/enforcement quote flows.
            
Not guaranteed to be monotonic: an admin correction can move phase backwards (e.g. Legal back
to Pre-legal).
            
Persists after case closure — reflects the case's last-known engagement phase, not the current
Lifecycle. Note: this is a different field from a lead quote's own offered phase (the phase a
partner's quote proposes to work the case at, if this case ever went through a quote flow) —
this field is the case-level phase of its actual engagement, not a quote's terms.
- `caseResults.successfulCases[].claimType` (string, nullable): The type of claim for this case (e.g. "Unpaid Invoice", "Loan Repayment", "Breach of Contract").
Null if not set.
- `caseResults.successfulCases[].creditorDivisionId` (uuid, nullable): 
- `caseResults.successfulCases[].debtor` (object): V1 Debtor DTO for external partner APIs.
The debtor is the party that owes the debt.
- `caseResults.successfulCases[].debtor.type` (string, required): Debtor type. Valid values: "Company" or "Private" (case-insensitive)
- `caseResults.successfulCases[].debtor.name` (string, required): Debtor name (company name or person's full name)
- `caseResults.successfulCases[].debtor.contactPerson` (string, nullable): Contact person at the company (required for companies, not used for persons)
- `caseResults.successfulCases[].debtor.companyRegistrationNumber` (string, nullable): Company registration number (VAT number, CVR, org number, etc.)
- `caseResults.successfulCases[].debtor.address` (string, nullable): Street address
- `caseResults.successfulCases[].debtor.zipCode` (string, nullable): Postal/ZIP code
- `caseResults.successfulCases[].debtor.city` (string, nullable): City name
- `caseResults.successfulCases[].debtor.state` (string, nullable): State/region/province name
- `caseResults.successfulCases[].debtor.stateAlpha2` (string, nullable): US state: two-letter code (e.g., "CA"), ISO 3166-2 format (e.g., "US-CA"), or full name (e.g., "California")
- `caseResults.successfulCases[].debtor.countryAlpha2` (string, nullable): Country code (ISO 3166-1 alpha-2 format)
- `caseResults.successfulCases[].debtor.country` (string, nullable): Country name
- `caseResults.successfulCases[].debtor.email` (string, nullable): Email address for debtor contact
- `caseResults.successfulCases[].debtor.phone` (string, nullable): Phone number (include country code)
- `caseResults.successfulCases[].collectionPartner` (object): V1 Collection Partner DTO for external partner APIs
- `caseResults.successfulCases[].collectionPartner.name` (string, nullable): 
- `caseResults.successfulCases[].collectionPartner.officeEmail` (string, nullable): 
- `caseResults.successfulCases[].collectionPartner.officePhone` (string, nullable): 
- `caseResults.successfulCases[].collectionPartner.publicSite` (string, nullable): 
- `caseResults.successfulCases[].collectionPartner.surveyCadenceMode` (enum, deprecated): Deprecated: kept as a number and never removed, but not extended. Survey-generation cadence: 0 = Standard
(rolling monthly survey), 1 = DecisionPointOnly (no rolling surveys).
  Values: `0`, `1`.
- `caseResults.successfulCases[].creditor` (object): Creditor (client) information for external partner APIs.
Represents the party that the debtor owes money to.
- `caseResults.successfulCases[].creditor.id` (uuid): Unique identifier for the creditor
- `caseResults.successfulCases[].creditor.companyName` (string, nullable): Company name of the creditor
- `caseResults.successfulCases[].creditor.companyRegistrationNumber` (string, nullable): Company registration number (CVR, VAT number, etc.)
- `caseResults.successfulCases[].creditor.officeEmail` (string, nullable): Primary office email address
- `caseResults.successfulCases[].creditor.officePhone` (string, nullable): Primary office phone number
- `caseResults.successfulCases[].creditor.address` (string, nullable): Street address
- `caseResults.successfulCases[].creditor.city` (string, nullable): City
- `caseResults.successfulCases[].creditor.zipCode` (string, nullable): Postal/ZIP code
- `caseResults.successfulCases[].creditor.state` (string, nullable): State or region (if applicable)
- `caseResults.successfulCases[].creditor.country` (string, nullable): Country name
- `caseResults.successfulCases[].creditor.division` (object): Creditor division information for external partner APIs.
Represents a specific division or department within a creditor organization.
- `caseResults.successfulCases[].creditor.division.id` (uuid): Unique identifier for the division
- `caseResults.successfulCases[].creditor.division.name` (string, nullable): Name of the division
- `caseResults.successfulCases[].bankAccount` (object): Bank account information for partner API.
Full details provided as partners need this to:
1. Provide payment instructions to debtors (when debtor pays client directly)
2. Execute payouts to clients (when partner receives payment and pays out remainder)
- `caseResults.successfulCases[].bankAccount.id` (integer): Bank account identifier
- `caseResults.successfulCases[].bankAccount.label` (string, nullable): User-friendly label (e.g., "Main EUR Account")
- `caseResults.successfulCases[].bankAccount.scheme` (string, nullable): Account scheme: IBAN, SWIFT, or LOCAL
- `caseResults.successfulCases[].bankAccount.currencyCode` (string, nullable): Currency code (ISO 4217)
- `caseResults.successfulCases[].bankAccount.bankCountryCode` (string, nullable): Bank country code (ISO Alpha-2)
- `caseResults.successfulCases[].bankAccount.accountHolderName` (string, nullable): Account holder name (beneficiary)
- `caseResults.successfulCases[].bankAccount.iban` (string, nullable): IBAN (for IBAN scheme accounts)
- `caseResults.successfulCases[].bankAccount.bic` (string, nullable): BIC/SWIFT code (for IBAN and SWIFT scheme accounts)
- `caseResults.successfulCases[].bankAccount.accountNumber` (string, nullable): Account number (for SWIFT and LOCAL scheme accounts)
- `caseResults.successfulCases[].bankAccount.localIdentifier` (string, nullable): Local identifier (for LOCAL scheme accounts, e.g., sort code + account number)
- `caseResults.successfulCases[].bankAccount.localIdentifierType` (string, nullable): Type of local identifier (e.g., "Sort Code", "Routing Number")
- `caseResults.successfulCases[].bankAccount.bankName` (string, nullable): Bank name (optional)
- `caseResults.successfulCases[].bankAccount.bankAddress` (string, nullable): Bank address (optional)
- `caseResults.successfulCases[].bankAccount.bankCity` (string, nullable): Bank city (optional)
- `caseResults.successfulCases[].bankAccount.bankZipCode` (string, nullable): Bank zip/postal code (optional)
- `caseResults.successfulCases[].bankAccount.bankState` (string, nullable): Bank state/region (optional)
- `caseResults.successfulCases[].blendedAgeUpliftPoints` (number, nullable): MULTI-INVOICE AGE BUCKET PRICING
Calculated blended age uplift percentage points (0-20) for multi-invoice cases.
Shows the additional fee percentage added due to invoice age.
Formula: ((A12-A24)×10 + A24×20) / Total Principal
Null for single-invoice cases (age uplift is calculated from due date instead).
- `caseResults.successfulCases[].preLegalSuccessFee` (number, nullable): PRE-LEGAL SUCCESS FEE
The total pre-legal success fee percentage for this case.
Includes base fee + age-based uplift (blended or single-invoice).
Null if pricing has not been calculated yet or if case is not in pre-legal phase.
Example: 20.5 represents 20.5% success fee.
- `caseResults.successfulCases[].solutionUrl` (string, nullable, deprecated): When the case is created with allowPendingContracts=true and required contracts are unsigned,
this URL points to the signing page. Null when contracts are already signed or not applicable.
- `caseResults.successfulCases[].signingHandoff` (object): Partner-facing handoff metadata for a creditor's pending signing chain.
Returned on POST /cases responses (422 with pending-signing errors,
or 200 with AllowPendingContracts=true when signings remain).
            
Designed as an envelope so future fields (expiration, suggested email
copy, etc.) can be added without polluting the parent DTO.
- `caseResults.successfulCases[].signingHandoff.combinedSigningUrl` (string, nullable): Single signing entry URL that walks the creditor through every
pending step (SDCA upgrade → PoA → JPA → KYC) on the Creditors app
and returns to the partner-supplied returnUrl when done.
- `caseResults.successfulCases[].exclusivePeriodEndDate` (datetime, nullable): The date the exclusive collection period ends (or ended).
Null if no collection period has been created for this case (e.g. custom-terms cases).
Use GET /cases/{id}/exclusive-period for the full chain including extensions.
- `caseResults.successfulCases[].disputeStatus` (string, nullable): Whether the claim is disputed by the debtor.
One of: "Yes, the claim is disputed", "No, the claim is not disputed", or "Don't Know".
Null when the dispute status has not been set on the case.
- `caseResults.successfulCases[].validation` (object): Stable v1 validation summary used by ordinary and list mappings.
- `caseResults.successfulCases[].validation.needsInfo` (boolean): 
- `caseResults.successfulCases[].assignedUser` (object): Represents the creditor team member assigned to a case.
- `caseResults.successfulCases[].assignedUser.email` (string, nullable): The assigned user's email address.
- `caseResults.successfulCases[].assignedUser.name` (string, nullable): The assigned user's full name.
- `caseResults.successfulCases[].allocationOutstanding` (object): Outstanding amount per bucket on the case: each bucket's total minus the payments allocated to it.
- `caseResults.successfulCases[].allocationOutstanding.principal` (number): 
- `caseResults.successfulCases[].allocationOutstanding.interest` (number): 
- `caseResults.successfulCases[].allocationOutstanding.reminderFees` (number): 
- `caseResults.successfulCases[].allocationOutstanding.collectionFees` (number): 
- `caseResults.failedCases` (array of objects, nullable): Cases that failed during creation.
Each element contains error details and the original case index.
- `caseResults.failedCases[].caseIndex` (integer): Zero-based index of the failed case in the original Cases array.
- `caseResults.failedCases[].creditorReference` (string, nullable): Creditor reference from the failed case, if provided.
Helps consumers identify which specific case failed.
- `caseResults.failedCases[].errorType` (string, nullable): Machine-readable error type code for programmatic error handling.
Enables API consumers to handle different failure scenarios without parsing error messages.
            

<b>Possible values:</b><list type="bullet"><item><term>NoPartnerAvailable</term><description>No collection partner available for the debtor's jurisdiction.
The debtor is in a country/region where Debitura does not yet have collection partner coverage.
Consider resubmitting with debtors in supported jurisdictions.</description></item><item><term>ValidationError</term><description>The request failed field-level validation.
Check the ValidationErrors property for detailed field-specific errors.
Common causes: missing required fields, invalid formats, business rule violations.</description></item><item><term>DuplicateReference</term><description>The provided CreditorReference already exists for this creditor or is duplicated in the current request.
CreditorReference must be unique per creditor.</description></item><item><term>IdempotencyViolation</term><description>The client has already been created in a previous API call.
Cases are not created on repeated calls to maintain idempotency.
This is informational - the original operation already succeeded.</description></item><item><term>UnexpectedError</term><description>An unexpected system error occurred during case creation.
This is a catch-all for errors not covered by other types.
Contact Debitura support if this error persists.</description></item></list>
Null if the error type cannot be determined or is not applicable.
- `caseResults.failedCases[].errorMessage` (string, nullable): High-level error message explaining why the case creation failed.
- `caseResults.failedCases[].validationErrors` (object, nullable): Detailed field-level validation errors if the failure was due to validation.
Null if the failure was due to other reasons (e.g., no partner match).
- `caseResults.failedCases[].signingHandoff` (object): Partner-facing handoff metadata for a creditor's pending signing chain.
Returned on POST /cases responses (422 with pending-signing errors,
or 200 with AllowPendingContracts=true when signings remain).
            
Designed as an envelope so future fields (expiration, suggested email
copy, etc.) can be added without polluting the parent DTO.
- `caseResults.failedCases[].signingHandoff.combinedSigningUrl` (string, nullable): Single signing entry URL that walks the creditor through every
pending step (SDCA upgrade → PoA → JPA → KYC) on the Creditors app
and returns to the partner-supplied returnUrl when done.

```json
{
  "externalTenantId": "string",
  "onboardingDone": true,
  "onboardingLinks": {
    "url": "https://app.debitura.com/…"
  },
  "client": {
    "id": "3f2b6c1e-8a4d-4b7f-9c2e-5d1a0b9e7f31",
    "companyName": "Muster GmbH",
    "officeEmail": "finance@example.com",
    "country": "Germany",
    "address": "Friedrichstraße 68",
    "city": "Berlin",
    "zipCode": "10115",
    "companyRegistrationNumber": "DE123456789"
  },
  "users": [
    {
      "id": 3,
      "email": "finance@example.com",
      "firstName": "Anna",
      "lastName": "Schmidt"
    }
  ],
  "isAttributedClient": true,
  "dateLinked": "2026-10-01T14:05:00Z",
  "caseStats": {
    "casesTotal": 42,
    "casesClosed": 3,
    "earningsUsd": 1.5
  },
  "kycStatus": "NotRequired",
  "kycVerification": {
    "directorFullName": "Muster GmbH",
    "directorHomeAddress": "Friedrichstraße 68",
    "directorDateOfBirth": "2026-10-01",
    "dateCreated": "2026-10-01T14:05:00Z",
    "verificationStatus": "Processing",
    "verificationStatusUpdatedAt": "2026-10-01T14:05:00Z"
  },
  "caseResults": {
    "successfulCases": [
      {
        "id": "3f2b6c1e-8a4d-4b7f-9c2e-5d1a0b9e7f31",
        "dateCreated": "2026-10-01T14:05:00Z",
        "dateUpdated": "2026-10-01T14:05:00Z",
        "reference": "INV-2026-0042",
        "creditorReference": "INV-2026-0042",
        "creditorComments": "Payment plan agreed with the debtor.",
        "claimDescription": "string",
        "grossAmount": 2500,
        "remainder": 1.5,
        "interestFees": 2500,
        "reminderFees": 2500,
        "collectionFees": 2500,
        "totalAddedFees": 2500,
        "currency": "EUR",
        "isTestCase": true,
        "lifecycle": "string",
        "dueDate": "2026-10-01T14:05:00Z",
        "date": "2026-10-01T14:05:00Z",
        "dateFinished": "2026-10-01T14:05:00Z",
        "dateCollectionStarted": "2026-10-01T14:05:00Z",
        "closeCode": "string",
        "currentEngagementPhase": "string",
        "claimType": "string",
        "creditorDivisionId": "3f2b6c1e-8a4d-4b7f-9c2e-5d1a0b9e7f31",
        "debtor": {
          "type": "Company",
          "name": "Pacific Trading LLC",
          "contactPerson": "John Smith",
          "companyRegistrationNumber": "47-1234567",
          "address": "123 Market Street, Suite 400",
          "zipCode": "94105",
          "city": "San Francisco",
          "state": "California",
          "stateAlpha2": "CA",
          "countryAlpha2": "US",
          "country": "United States",
          "email": "accounts@pacifictrading.com",
          "phone": "+1 415 555 0123"
        },
        "collectionPartner": {
          "name": {},
          "officeEmail": {},
          "officePhone": {},
          "publicSite": {},
          "surveyCadenceMode": {}
        },
        "creditor": {
          "id": {},
          "companyName": {},
          "companyRegistrationNumber": {},
          "officeEmail": {},
          "officePhone": {},
          "address": {},
          "city": {},
          "zipCode": {},
          "state": {},
          "country": {},
          "division": {}
        },
        "bankAccount": {
          "id": {},
          "label": {},
          "scheme": {},
          "currencyCode": {},
          "bankCountryCode": {},
          "accountHolderName": {},
          "iban": {},
          "bic": {},
          "accountNumber": {},
          "localIdentifier": {},
          "localIdentifierType": {},
          "bankName": {},
          "bankAddress": {},
          "bankCity": {},
          "bankZipCode": {},
          "bankState": {}
        },
        "blendedAgeUpliftPoints": 1.5,
        "preLegalSuccessFee": 2500,
        "solutionUrl": "https://app.debitura.com/…",
        "signingHandoff": {
          "combinedSigningUrl": {}
        },
        "exclusivePeriodEndDate": "2026-10-01T14:05:00Z",
        "disputeStatus": "string",
        "validation": {
          "needsInfo": {}
        },
        "assignedUser": {
          "email": {},
          "name": {}
        },
        "allocationOutstanding": {
          "principal": {},
          "interest": {},
          "reminderFees": {},
          "collectionFees": {}
        }
      }
    ],
    "failedCases": [
      {
        "caseIndex": 3,
        "creditorReference": "INV-2026-0042",
        "errorType": null,
        "errorMessage": null,
        "validationErrors": {},
        "signingHandoff": {
          "combinedSigningUrl": {}
        }
      }
    ]
  }
}
```

### Response 400

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.

```json
{}
```

### Response 409

Client/link conflict or an identical Idempotency-Key request still in progress. Approval-required responses use Type/Message/Data; in-progress responses use businessErrors[0].type = IdempotencyKeyInProgress and include Retry-After: 2.

- `type` (string, nullable): 
- `message` (string, nullable): 
- `data` (any, nullable): 
- `businessErrors` (array of objects, nullable): Represents a business error in the API response.
- `businessErrors[].type` (string, nullable): The type of business error (e.g., "MissingDebtCollectionContract", "MissingPowerOfAttorney", "NoPartnerAvailable").
- `businessErrors[].message` (string, nullable): A human-readable description of the error.
- `businessErrors[].solutionUrl` (string, nullable): A URL where the user can resolve this <i>specific</i> error (e.g., sign a contract).
            

Partners who want a <b>single URL</b> that walks the user through every pending
signing in one chain — instead of forwarding one URL per
`BusinessErrorApiDTO` — should use
SigningHandoff's `CombinedSigningUrl`.
The two are complementary: `SolutionUrl` is granular per-error;
`CombinedSigningUrl` is the chain-walking alternative for signing-related errors.
- `signingHandoff` (object): Partner-facing handoff metadata for a creditor's pending signing chain.
Returned on POST /cases responses (422 with pending-signing errors,
or 200 with AllowPendingContracts=true when signings remain).
            
Designed as an envelope so future fields (expiration, suggested email
copy, etc.) can be added without polluting the parent DTO.
- `signingHandoff.combinedSigningUrl` (string, nullable): Single signing entry URL that walks the creditor through every
pending step (SDCA upgrade → PoA → JPA → KYC) on the Creditors app
and returns to the partner-supplied returnUrl when done.

```json
{
  "type": "string",
  "message": "Payment plan agreed with the debtor.",
  "data": null,
  "businessErrors": [
    {
      "type": "string",
      "message": "Payment plan agreed with the debtor.",
      "solutionUrl": "https://app.debitura.com/…"
    }
  ],
  "signingHandoff": {
    "combinedSigningUrl": "https://app.debitura.com/…"
  }
}
```

### Response 422

Business rule violation, including businessErrors[0].type = IdempotencyConflict when the same Idempotency-Key is reused with a different effective request body.

- `businessErrors` (array of objects, nullable): List of business errors that must be resolved before the case can be created.
- `businessErrors[].type` (string, nullable): The type of business error (e.g., "MissingDebtCollectionContract", "MissingPowerOfAttorney", "NoPartnerAvailable").
- `businessErrors[].message` (string, nullable): A human-readable description of the error.
- `businessErrors[].solutionUrl` (string, nullable): A URL where the user can resolve this <i>specific</i> error (e.g., sign a contract).
            

Partners who want a <b>single URL</b> that walks the user through every pending
signing in one chain — instead of forwarding one URL per
`BusinessErrorApiDTO` — should use
SigningHandoff's `CombinedSigningUrl`.
The two are complementary: `SolutionUrl` is granular per-error;
`CombinedSigningUrl` is the chain-walking alternative for signing-related errors.
- `signingHandoff` (object): Partner-facing handoff metadata for a creditor's pending signing chain.
Returned on POST /cases responses (422 with pending-signing errors,
or 200 with AllowPendingContracts=true when signings remain).
            
Designed as an envelope so future fields (expiration, suggested email
copy, etc.) can be added without polluting the parent DTO.
- `signingHandoff.combinedSigningUrl` (string, nullable): Single signing entry URL that walks the creditor through every
pending step (SDCA upgrade → PoA → JPA → KYC) on the Creditors app
and returns to the partner-supplied returnUrl when done.

```json
{
  "businessErrors": [
    {
      "type": "string",
      "message": "Payment plan agreed with the debtor.",
      "solutionUrl": "https://app.debitura.com/…"
    }
  ],
  "signingHandoff": {
    "combinedSigningUrl": "https://app.debitura.com/…"
  }
}
```

### Response 500

Internal server error

- `error` (string, nullable): Short human-readable error label (legacy field — preserved for backward compatibility).
- `message` (string, nullable): Human-readable error description (legacy field — preserved for backward compatibility).
- `businessErrors` (array of objects, nullable): Canonical structured error array. Consumers should migrate to reading this field.
- `businessErrors[].type` (string, nullable): The type of business error (e.g., "MissingDebtCollectionContract", "MissingPowerOfAttorney", "NoPartnerAvailable").
- `businessErrors[].message` (string, nullable): A human-readable description of the error.
- `businessErrors[].solutionUrl` (string, nullable): A URL where the user can resolve this <i>specific</i> error (e.g., sign a contract).
            

Partners who want a <b>single URL</b> that walks the user through every pending
signing in one chain — instead of forwarding one URL per
`BusinessErrorApiDTO` — should use
SigningHandoff's `CombinedSigningUrl`.
The two are complementary: `SolutionUrl` is granular per-error;
`CombinedSigningUrl` is the chain-walking alternative for signing-related errors.

```json
{
  "error": null,
  "message": "Payment plan agreed with the debtor.",
  "businessErrors": [
    {
      "type": "string",
      "message": "Payment plan agreed with the debtor.",
      "solutionUrl": "https://app.debitura.com/…"
    }
  ]
}
```

<a id="get-client-by-external-tenant-id"></a>

## Get client by external tenant ID

`GET /clients/{externalTenantId}`

Retrieves detailed information for a specific client using your unique identifier (External Tenant ID).

Path Parameter
- **externalTenantId** - Your unique identifier for this client (the same value used during client creation)

Response Data
The response includes complete client information:
- **ExternalTenantId** - Your unique identifier for this client
- **OnboardingDone** - Whether the client has completed onboarding (signed debt collection agreements)
- **OnboardingLinks** - If onboarding incomplete, contains URL to complete the process
- **Client** - Complete client information
  - Debitura-assigned client ID (Guid)
  - Company name and registration number
  - Country and address details
  - Contact information (email, phone)
- **Users** - List of all users associated with this client
  - User ID, email, first name, last name

Use Cases
- Look up client details using your internal identifier
- Check client onboarding status
- Retrieve Debitura client ID for use with the Customer API (via OAuth token endpoint)
- Get client information before creating cases
- Verify client link is still active

Error Cases
- **404 Not Found** - No active client link exists for this External Tenant ID and your partner account
  - Client was never created
  - Client link was archived
  - External Tenant ID belongs to different referral partner
- **500 Internal Server Error** - Unexpected server error

Important Notes
- Only returns active (non-archived) client links
- External Tenant ID is case-sensitive
- The client must be linked to your referral partner account
- Use the returned client ID with the OAuth token endpoint to generate bearer tokens for Customer API access

### Path parameters

- `externalTenantId` (string, required): 

### Response 200

Client retrieved successfully

- `externalTenantId` (string, nullable): 
- `onboardingDone` (boolean): 
- `onboardingLinks` (object): 
- `onboardingLinks.url` (string, nullable): 
- `client` (object): 
- `client.id` (uuid): 
- `client.companyName` (string, nullable): 
- `client.officeEmail` (string, nullable): 
- `client.country` (string, nullable): 
- `client.address` (string, nullable): 
- `client.city` (string, nullable): 
- `client.zipCode` (string, nullable): 
- `client.companyRegistrationNumber` (string, nullable): 
- `users` (array of objects, nullable): 
- `users[].id` (integer): 
- `users[].email` (string, nullable): 
- `users[].firstName` (string, nullable): 
- `users[].lastName` (string, nullable): 
- `isAttributedClient` (boolean): 
- `dateLinked` (datetime): 
- `caseStats` (object): 
- `caseStats.casesTotal` (integer): 
- `caseStats.casesClosed` (integer): 
- `caseStats.earningsUsd` (number): 
- `kycStatus` (enum): KYC (Know Your Customer) verification status for a client linked to a referral partner.
Captures three distinct states that a simple boolean cannot express.
Sent as snake_case string values: "not_required", "pending", "verified".
  Values: `NotRequired`, `Pending`, `Verified`.
- `kycVerification` (object): 
- `kycVerification.directorFullName` (string, nullable): 
- `kycVerification.directorHomeAddress` (string, nullable): 
- `kycVerification.directorDateOfBirth` (date): 
- `kycVerification.dateCreated` (datetime): 
- `kycVerification.verificationStatus` (enum, nullable): Partner/staff-set review status (Processing/Completed) for this submission. Null = not yet
reviewed. Note: distinct from the sibling `ClientResponse.KycStatus` field, which
describes whether KYC data has been submitted at all.
  Values: `Processing`, `Completed`, `null`.
- `kycVerification.verificationStatusUpdatedAt` (datetime, nullable): When VerificationStatus was last set. Null until set.
- `caseResults` (object): Result of creating multiple cases during client creation.
Groups successful and failed case creation attempts.
- `caseResults.successfulCases` (array of objects, nullable): Cases that were created successfully.
Each element contains the full case details.
- `caseResults.successfulCases[].id` (uuid): 
- `caseResults.successfulCases[].dateCreated` (datetime): 
- `caseResults.successfulCases[].dateUpdated` (datetime, nullable): 
- `caseResults.successfulCases[].reference` (string, nullable): 
- `caseResults.successfulCases[].creditorReference` (string, nullable): 
- `caseResults.successfulCases[].creditorComments` (string, nullable): 
- `caseResults.successfulCases[].claimDescription` (string, nullable): 
- `caseResults.successfulCases[].grossAmount` (number): 
- `caseResults.successfulCases[].remainder` (number): 
- `caseResults.successfulCases[].interestFees` (number): 
- `caseResults.successfulCases[].reminderFees` (number): 
- `caseResults.successfulCases[].collectionFees` (number): 
- `caseResults.successfulCases[].totalAddedFees` (number): 
- `caseResults.successfulCases[].currency` (string, nullable): 
- `caseResults.successfulCases[].isTestCase` (boolean): 
- `caseResults.successfulCases[].lifecycle` (string, nullable): 
- `caseResults.successfulCases[].dueDate` (datetime): 
- `caseResults.successfulCases[].date` (datetime): 
- `caseResults.successfulCases[].dateFinished` (datetime, nullable): 
- `caseResults.successfulCases[].dateCollectionStarted` (datetime, nullable): 
- `caseResults.successfulCases[].closeCode` (string, nullable): 
- `caseResults.successfulCases[].currentEngagementPhase` (string, nullable): The current phase of the case's engagement: "Pre-legal", "Legal", or "Enforcement".
A different axis from Lifecycle/CloseCode — an Active case can be
in any of the three phases.
            
Null means "no active engagement" (e.g. lead / quoting / pre-contract-signing / unassigned, or
a data-consistency gap) — this is a distinct third state, NOT a synonym for Pre-legal. Most
cases legitimately read Pre-legal; phase only leaves Pre-legal on legal/enforcement quote flows.
            
Not guaranteed to be monotonic: an admin correction can move phase backwards (e.g. Legal back
to Pre-legal).
            
Persists after case closure — reflects the case's last-known engagement phase, not the current
Lifecycle. Note: this is a different field from a lead quote's own offered phase (the phase a
partner's quote proposes to work the case at, if this case ever went through a quote flow) —
this field is the case-level phase of its actual engagement, not a quote's terms.
- `caseResults.successfulCases[].claimType` (string, nullable): The type of claim for this case (e.g. "Unpaid Invoice", "Loan Repayment", "Breach of Contract").
Null if not set.
- `caseResults.successfulCases[].creditorDivisionId` (uuid, nullable): 
- `caseResults.successfulCases[].debtor` (object): V1 Debtor DTO for external partner APIs.
The debtor is the party that owes the debt.
- `caseResults.successfulCases[].debtor.type` (string, required): Debtor type. Valid values: "Company" or "Private" (case-insensitive)
- `caseResults.successfulCases[].debtor.name` (string, required): Debtor name (company name or person's full name)
- `caseResults.successfulCases[].debtor.contactPerson` (string, nullable): Contact person at the company (required for companies, not used for persons)
- `caseResults.successfulCases[].debtor.companyRegistrationNumber` (string, nullable): Company registration number (VAT number, CVR, org number, etc.)
- `caseResults.successfulCases[].debtor.address` (string, nullable): Street address
- `caseResults.successfulCases[].debtor.zipCode` (string, nullable): Postal/ZIP code
- `caseResults.successfulCases[].debtor.city` (string, nullable): City name
- `caseResults.successfulCases[].debtor.state` (string, nullable): State/region/province name
- `caseResults.successfulCases[].debtor.stateAlpha2` (string, nullable): US state: two-letter code (e.g., "CA"), ISO 3166-2 format (e.g., "US-CA"), or full name (e.g., "California")
- `caseResults.successfulCases[].debtor.countryAlpha2` (string, nullable): Country code (ISO 3166-1 alpha-2 format)
- `caseResults.successfulCases[].debtor.country` (string, nullable): Country name
- `caseResults.successfulCases[].debtor.email` (string, nullable): Email address for debtor contact
- `caseResults.successfulCases[].debtor.phone` (string, nullable): Phone number (include country code)
- `caseResults.successfulCases[].collectionPartner` (object): V1 Collection Partner DTO for external partner APIs
- `caseResults.successfulCases[].collectionPartner.name` (string, nullable): 
- `caseResults.successfulCases[].collectionPartner.officeEmail` (string, nullable): 
- `caseResults.successfulCases[].collectionPartner.officePhone` (string, nullable): 
- `caseResults.successfulCases[].collectionPartner.publicSite` (string, nullable): 
- `caseResults.successfulCases[].collectionPartner.surveyCadenceMode` (enum, deprecated): Deprecated: kept as a number and never removed, but not extended. Survey-generation cadence: 0 = Standard
(rolling monthly survey), 1 = DecisionPointOnly (no rolling surveys).
  Values: `0`, `1`.
- `caseResults.successfulCases[].creditor` (object): Creditor (client) information for external partner APIs.
Represents the party that the debtor owes money to.
- `caseResults.successfulCases[].creditor.id` (uuid): Unique identifier for the creditor
- `caseResults.successfulCases[].creditor.companyName` (string, nullable): Company name of the creditor
- `caseResults.successfulCases[].creditor.companyRegistrationNumber` (string, nullable): Company registration number (CVR, VAT number, etc.)
- `caseResults.successfulCases[].creditor.officeEmail` (string, nullable): Primary office email address
- `caseResults.successfulCases[].creditor.officePhone` (string, nullable): Primary office phone number
- `caseResults.successfulCases[].creditor.address` (string, nullable): Street address
- `caseResults.successfulCases[].creditor.city` (string, nullable): City
- `caseResults.successfulCases[].creditor.zipCode` (string, nullable): Postal/ZIP code
- `caseResults.successfulCases[].creditor.state` (string, nullable): State or region (if applicable)
- `caseResults.successfulCases[].creditor.country` (string, nullable): Country name
- `caseResults.successfulCases[].creditor.division` (object): Creditor division information for external partner APIs.
Represents a specific division or department within a creditor organization.
- `caseResults.successfulCases[].creditor.division.id` (uuid): Unique identifier for the division
- `caseResults.successfulCases[].creditor.division.name` (string, nullable): Name of the division
- `caseResults.successfulCases[].bankAccount` (object): Bank account information for partner API.
Full details provided as partners need this to:
1. Provide payment instructions to debtors (when debtor pays client directly)
2. Execute payouts to clients (when partner receives payment and pays out remainder)
- `caseResults.successfulCases[].bankAccount.id` (integer): Bank account identifier
- `caseResults.successfulCases[].bankAccount.label` (string, nullable): User-friendly label (e.g., "Main EUR Account")
- `caseResults.successfulCases[].bankAccount.scheme` (string, nullable): Account scheme: IBAN, SWIFT, or LOCAL
- `caseResults.successfulCases[].bankAccount.currencyCode` (string, nullable): Currency code (ISO 4217)
- `caseResults.successfulCases[].bankAccount.bankCountryCode` (string, nullable): Bank country code (ISO Alpha-2)
- `caseResults.successfulCases[].bankAccount.accountHolderName` (string, nullable): Account holder name (beneficiary)
- `caseResults.successfulCases[].bankAccount.iban` (string, nullable): IBAN (for IBAN scheme accounts)
- `caseResults.successfulCases[].bankAccount.bic` (string, nullable): BIC/SWIFT code (for IBAN and SWIFT scheme accounts)
- `caseResults.successfulCases[].bankAccount.accountNumber` (string, nullable): Account number (for SWIFT and LOCAL scheme accounts)
- `caseResults.successfulCases[].bankAccount.localIdentifier` (string, nullable): Local identifier (for LOCAL scheme accounts, e.g., sort code + account number)
- `caseResults.successfulCases[].bankAccount.localIdentifierType` (string, nullable): Type of local identifier (e.g., "Sort Code", "Routing Number")
- `caseResults.successfulCases[].bankAccount.bankName` (string, nullable): Bank name (optional)
- `caseResults.successfulCases[].bankAccount.bankAddress` (string, nullable): Bank address (optional)
- `caseResults.successfulCases[].bankAccount.bankCity` (string, nullable): Bank city (optional)
- `caseResults.successfulCases[].bankAccount.bankZipCode` (string, nullable): Bank zip/postal code (optional)
- `caseResults.successfulCases[].bankAccount.bankState` (string, nullable): Bank state/region (optional)
- `caseResults.successfulCases[].blendedAgeUpliftPoints` (number, nullable): MULTI-INVOICE AGE BUCKET PRICING
Calculated blended age uplift percentage points (0-20) for multi-invoice cases.
Shows the additional fee percentage added due to invoice age.
Formula: ((A12-A24)×10 + A24×20) / Total Principal
Null for single-invoice cases (age uplift is calculated from due date instead).
- `caseResults.successfulCases[].preLegalSuccessFee` (number, nullable): PRE-LEGAL SUCCESS FEE
The total pre-legal success fee percentage for this case.
Includes base fee + age-based uplift (blended or single-invoice).
Null if pricing has not been calculated yet or if case is not in pre-legal phase.
Example: 20.5 represents 20.5% success fee.
- `caseResults.successfulCases[].solutionUrl` (string, nullable, deprecated): When the case is created with allowPendingContracts=true and required contracts are unsigned,
this URL points to the signing page. Null when contracts are already signed or not applicable.
- `caseResults.successfulCases[].signingHandoff` (object): Partner-facing handoff metadata for a creditor's pending signing chain.
Returned on POST /cases responses (422 with pending-signing errors,
or 200 with AllowPendingContracts=true when signings remain).
            
Designed as an envelope so future fields (expiration, suggested email
copy, etc.) can be added without polluting the parent DTO.
- `caseResults.successfulCases[].signingHandoff.combinedSigningUrl` (string, nullable): Single signing entry URL that walks the creditor through every
pending step (SDCA upgrade → PoA → JPA → KYC) on the Creditors app
and returns to the partner-supplied returnUrl when done.
- `caseResults.successfulCases[].exclusivePeriodEndDate` (datetime, nullable): The date the exclusive collection period ends (or ended).
Null if no collection period has been created for this case (e.g. custom-terms cases).
Use GET /cases/{id}/exclusive-period for the full chain including extensions.
- `caseResults.successfulCases[].disputeStatus` (string, nullable): Whether the claim is disputed by the debtor.
One of: "Yes, the claim is disputed", "No, the claim is not disputed", or "Don't Know".
Null when the dispute status has not been set on the case.
- `caseResults.successfulCases[].validation` (object): Stable v1 validation summary used by ordinary and list mappings.
- `caseResults.successfulCases[].validation.needsInfo` (boolean): 
- `caseResults.successfulCases[].assignedUser` (object): Represents the creditor team member assigned to a case.
- `caseResults.successfulCases[].assignedUser.email` (string, nullable): The assigned user's email address.
- `caseResults.successfulCases[].assignedUser.name` (string, nullable): The assigned user's full name.
- `caseResults.successfulCases[].allocationOutstanding` (object): Outstanding amount per bucket on the case: each bucket's total minus the payments allocated to it.
- `caseResults.successfulCases[].allocationOutstanding.principal` (number): 
- `caseResults.successfulCases[].allocationOutstanding.interest` (number): 
- `caseResults.successfulCases[].allocationOutstanding.reminderFees` (number): 
- `caseResults.successfulCases[].allocationOutstanding.collectionFees` (number): 
- `caseResults.failedCases` (array of objects, nullable): Cases that failed during creation.
Each element contains error details and the original case index.
- `caseResults.failedCases[].caseIndex` (integer): Zero-based index of the failed case in the original Cases array.
- `caseResults.failedCases[].creditorReference` (string, nullable): Creditor reference from the failed case, if provided.
Helps consumers identify which specific case failed.
- `caseResults.failedCases[].errorType` (string, nullable): Machine-readable error type code for programmatic error handling.
Enables API consumers to handle different failure scenarios without parsing error messages.
            

<b>Possible values:</b><list type="bullet"><item><term>NoPartnerAvailable</term><description>No collection partner available for the debtor's jurisdiction.
The debtor is in a country/region where Debitura does not yet have collection partner coverage.
Consider resubmitting with debtors in supported jurisdictions.</description></item><item><term>ValidationError</term><description>The request failed field-level validation.
Check the ValidationErrors property for detailed field-specific errors.
Common causes: missing required fields, invalid formats, business rule violations.</description></item><item><term>DuplicateReference</term><description>The provided CreditorReference already exists for this creditor or is duplicated in the current request.
CreditorReference must be unique per creditor.</description></item><item><term>IdempotencyViolation</term><description>The client has already been created in a previous API call.
Cases are not created on repeated calls to maintain idempotency.
This is informational - the original operation already succeeded.</description></item><item><term>UnexpectedError</term><description>An unexpected system error occurred during case creation.
This is a catch-all for errors not covered by other types.
Contact Debitura support if this error persists.</description></item></list>
Null if the error type cannot be determined or is not applicable.
- `caseResults.failedCases[].errorMessage` (string, nullable): High-level error message explaining why the case creation failed.
- `caseResults.failedCases[].validationErrors` (object, nullable): Detailed field-level validation errors if the failure was due to validation.
Null if the failure was due to other reasons (e.g., no partner match).
- `caseResults.failedCases[].signingHandoff` (object): Partner-facing handoff metadata for a creditor's pending signing chain.
Returned on POST /cases responses (422 with pending-signing errors,
or 200 with AllowPendingContracts=true when signings remain).
            
Designed as an envelope so future fields (expiration, suggested email
copy, etc.) can be added without polluting the parent DTO.
- `caseResults.failedCases[].signingHandoff.combinedSigningUrl` (string, nullable): Single signing entry URL that walks the creditor through every
pending step (SDCA upgrade → PoA → JPA → KYC) on the Creditors app
and returns to the partner-supplied returnUrl when done.

```json
{
  "externalTenantId": "string",
  "onboardingDone": true,
  "onboardingLinks": {
    "url": "https://app.debitura.com/…"
  },
  "client": {
    "id": "3f2b6c1e-8a4d-4b7f-9c2e-5d1a0b9e7f31",
    "companyName": "Muster GmbH",
    "officeEmail": "finance@example.com",
    "country": "Germany",
    "address": "Friedrichstraße 68",
    "city": "Berlin",
    "zipCode": "10115",
    "companyRegistrationNumber": "DE123456789"
  },
  "users": [
    {
      "id": 3,
      "email": "finance@example.com",
      "firstName": "Anna",
      "lastName": "Schmidt"
    }
  ],
  "isAttributedClient": true,
  "dateLinked": "2026-10-01T14:05:00Z",
  "caseStats": {
    "casesTotal": 42,
    "casesClosed": 3,
    "earningsUsd": 1.5
  },
  "kycStatus": "NotRequired",
  "kycVerification": {
    "directorFullName": "Muster GmbH",
    "directorHomeAddress": "Friedrichstraße 68",
    "directorDateOfBirth": "2026-10-01",
    "dateCreated": "2026-10-01T14:05:00Z",
    "verificationStatus": "Processing",
    "verificationStatusUpdatedAt": "2026-10-01T14:05:00Z"
  },
  "caseResults": {
    "successfulCases": [
      {
        "id": "3f2b6c1e-8a4d-4b7f-9c2e-5d1a0b9e7f31",
        "dateCreated": "2026-10-01T14:05:00Z",
        "dateUpdated": "2026-10-01T14:05:00Z",
        "reference": "INV-2026-0042",
        "creditorReference": "INV-2026-0042",
        "creditorComments": "Payment plan agreed with the debtor.",
        "claimDescription": "string",
        "grossAmount": 2500,
        "remainder": 1.5,
        "interestFees": 2500,
        "reminderFees": 2500,
        "collectionFees": 2500,
        "totalAddedFees": 2500,
        "currency": "EUR",
        "isTestCase": true,
        "lifecycle": "string",
        "dueDate": "2026-10-01T14:05:00Z",
        "date": "2026-10-01T14:05:00Z",
        "dateFinished": "2026-10-01T14:05:00Z",
        "dateCollectionStarted": "2026-10-01T14:05:00Z",
        "closeCode": "string",
        "currentEngagementPhase": "string",
        "claimType": "string",
        "creditorDivisionId": "3f2b6c1e-8a4d-4b7f-9c2e-5d1a0b9e7f31",
        "debtor": {
          "type": "Company",
          "name": "Pacific Trading LLC",
          "contactPerson": "John Smith",
          "companyRegistrationNumber": "47-1234567",
          "address": "123 Market Street, Suite 400",
          "zipCode": "94105",
          "city": "San Francisco",
          "state": "California",
          "stateAlpha2": "CA",
          "countryAlpha2": "US",
          "country": "United States",
          "email": "accounts@pacifictrading.com",
          "phone": "+1 415 555 0123"
        },
        "collectionPartner": {
          "name": {},
          "officeEmail": {},
          "officePhone": {},
          "publicSite": {},
          "surveyCadenceMode": {}
        },
        "creditor": {
          "id": {},
          "companyName": {},
          "companyRegistrationNumber": {},
          "officeEmail": {},
          "officePhone": {},
          "address": {},
          "city": {},
          "zipCode": {},
          "state": {},
          "country": {},
          "division": {}
        },
        "bankAccount": {
          "id": {},
          "label": {},
          "scheme": {},
          "currencyCode": {},
          "bankCountryCode": {},
          "accountHolderName": {},
          "iban": {},
          "bic": {},
          "accountNumber": {},
          "localIdentifier": {},
          "localIdentifierType": {},
          "bankName": {},
          "bankAddress": {},
          "bankCity": {},
          "bankZipCode": {},
          "bankState": {}
        },
        "blendedAgeUpliftPoints": 1.5,
        "preLegalSuccessFee": 2500,
        "solutionUrl": "https://app.debitura.com/…",
        "signingHandoff": {
          "combinedSigningUrl": {}
        },
        "exclusivePeriodEndDate": "2026-10-01T14:05:00Z",
        "disputeStatus": "string",
        "validation": {
          "needsInfo": {}
        },
        "assignedUser": {
          "email": {},
          "name": {}
        },
        "allocationOutstanding": {
          "principal": {},
          "interest": {},
          "reminderFees": {},
          "collectionFees": {}
        }
      }
    ],
    "failedCases": [
      {
        "caseIndex": 3,
        "creditorReference": "INV-2026-0042",
        "errorType": null,
        "errorMessage": null,
        "validationErrors": {},
        "signingHandoff": {
          "combinedSigningUrl": {}
        }
      }
    ]
  }
}
```

### Response 404

Client not found or link is archived

- `error` (string, nullable): Short human-readable error label (legacy field — preserved for backward compatibility).
- `message` (string, nullable): Human-readable error description (legacy field — preserved for backward compatibility).
- `businessErrors` (array of objects, nullable): Canonical structured error array. Consumers should migrate to reading this field.
- `businessErrors[].type` (string, nullable): The type of business error (e.g., "MissingDebtCollectionContract", "MissingPowerOfAttorney", "NoPartnerAvailable").
- `businessErrors[].message` (string, nullable): A human-readable description of the error.
- `businessErrors[].solutionUrl` (string, nullable): A URL where the user can resolve this <i>specific</i> error (e.g., sign a contract).
            

Partners who want a <b>single URL</b> that walks the user through every pending
signing in one chain — instead of forwarding one URL per
`BusinessErrorApiDTO` — should use
SigningHandoff's `CombinedSigningUrl`.
The two are complementary: `SolutionUrl` is granular per-error;
`CombinedSigningUrl` is the chain-walking alternative for signing-related errors.

```json
{
  "error": null,
  "message": "Payment plan agreed with the debtor.",
  "businessErrors": [
    {
      "type": "string",
      "message": "Payment plan agreed with the debtor.",
      "solutionUrl": "https://app.debitura.com/…"
    }
  ]
}
```

### Response 500

Internal server error

- `error` (string, nullable): Short human-readable error label (legacy field — preserved for backward compatibility).
- `message` (string, nullable): Human-readable error description (legacy field — preserved for backward compatibility).
- `businessErrors` (array of objects, nullable): Canonical structured error array. Consumers should migrate to reading this field.
- `businessErrors[].type` (string, nullable): The type of business error (e.g., "MissingDebtCollectionContract", "MissingPowerOfAttorney", "NoPartnerAvailable").
- `businessErrors[].message` (string, nullable): A human-readable description of the error.
- `businessErrors[].solutionUrl` (string, nullable): A URL where the user can resolve this <i>specific</i> error (e.g., sign a contract).
            

Partners who want a <b>single URL</b> that walks the user through every pending
signing in one chain — instead of forwarding one URL per
`BusinessErrorApiDTO` — should use
SigningHandoff's `CombinedSigningUrl`.
The two are complementary: `SolutionUrl` is granular per-error;
`CombinedSigningUrl` is the chain-walking alternative for signing-related errors.

```json
{
  "error": null,
  "message": "Payment plan agreed with the debtor.",
  "businessErrors": [
    {
      "type": "string",
      "message": "Payment plan agreed with the debtor.",
      "solutionUrl": "https://app.debitura.com/…"
    }
  ]
}
```

<a id="reset-a-client-test-environment-only"></a>

## Reset a client (test environment only)

`DELETE /clients/{externalTenantId}`

Deletes a client and all associated data, allowing you to re-create the client from scratch.

⚠️ **TEST ENVIRONMENT ONLY** - This endpoint is only available on the test environment (testreferral-api.debitura.com).
Calling this endpoint on production will return 403 Forbidden.

Use Cases
- Testing the full onboarding flow multiple times
- Resetting after changing your internal tenant structure during development
- Cleaning up test data without manual intervention

What Gets Deleted (cascade)
- All collection cases and invoices for the client
- All leads for the client
- The Creditor account (removes email from matching algorithm)
- The ReferralPartnerClientLink is archived
- Associated users are cleaned up if they have no other relations

After Reset
- You can call POST /clients with any externalTenantId using the same email
- The matching algorithm will not find the deleted client
- A completely new client will be created (IsAttributedClient=true)

Important
- You can only reset clients that are linked to your partner account
- Pending link requests (409 scenario) cannot be reset - only actual links

### Path parameters

- `externalTenantId` (string, required): 

### Response 204

Client and all associated data successfully deleted

### Response 403

Endpoint not available in production environment

- `error` (string, nullable): Short human-readable error label (legacy field — preserved for backward compatibility).
- `message` (string, nullable): Human-readable error description (legacy field — preserved for backward compatibility).
- `businessErrors` (array of objects, nullable): Canonical structured error array. Consumers should migrate to reading this field.
- `businessErrors[].type` (string, nullable): The type of business error (e.g., "MissingDebtCollectionContract", "MissingPowerOfAttorney", "NoPartnerAvailable").
- `businessErrors[].message` (string, nullable): A human-readable description of the error.
- `businessErrors[].solutionUrl` (string, nullable): A URL where the user can resolve this <i>specific</i> error (e.g., sign a contract).
            

Partners who want a <b>single URL</b> that walks the user through every pending
signing in one chain — instead of forwarding one URL per
`BusinessErrorApiDTO` — should use
SigningHandoff's `CombinedSigningUrl`.
The two are complementary: `SolutionUrl` is granular per-error;
`CombinedSigningUrl` is the chain-walking alternative for signing-related errors.

```json
{
  "error": null,
  "message": "Payment plan agreed with the debtor.",
  "businessErrors": [
    {
      "type": "string",
      "message": "Payment plan agreed with the debtor.",
      "solutionUrl": "https://app.debitura.com/…"
    }
  ]
}
```

### Response 404

No active client link found for this externalTenantId

- `error` (string, nullable): Short human-readable error label (legacy field — preserved for backward compatibility).
- `message` (string, nullable): Human-readable error description (legacy field — preserved for backward compatibility).
- `businessErrors` (array of objects, nullable): Canonical structured error array. Consumers should migrate to reading this field.
- `businessErrors[].type` (string, nullable): The type of business error (e.g., "MissingDebtCollectionContract", "MissingPowerOfAttorney", "NoPartnerAvailable").
- `businessErrors[].message` (string, nullable): A human-readable description of the error.
- `businessErrors[].solutionUrl` (string, nullable): A URL where the user can resolve this <i>specific</i> error (e.g., sign a contract).
            

Partners who want a <b>single URL</b> that walks the user through every pending
signing in one chain — instead of forwarding one URL per
`BusinessErrorApiDTO` — should use
SigningHandoff's `CombinedSigningUrl`.
The two are complementary: `SolutionUrl` is granular per-error;
`CombinedSigningUrl` is the chain-walking alternative for signing-related errors.

```json
{
  "error": null,
  "message": "Payment plan agreed with the debtor.",
  "businessErrors": [
    {
      "type": "string",
      "message": "Payment plan agreed with the debtor.",
      "solutionUrl": "https://app.debitura.com/…"
    }
  ]
}
```

### Response 500

Internal server error

- `error` (string, nullable): Short human-readable error label (legacy field — preserved for backward compatibility).
- `message` (string, nullable): Human-readable error description (legacy field — preserved for backward compatibility).
- `businessErrors` (array of objects, nullable): Canonical structured error array. Consumers should migrate to reading this field.
- `businessErrors[].type` (string, nullable): The type of business error (e.g., "MissingDebtCollectionContract", "MissingPowerOfAttorney", "NoPartnerAvailable").
- `businessErrors[].message` (string, nullable): A human-readable description of the error.
- `businessErrors[].solutionUrl` (string, nullable): A URL where the user can resolve this <i>specific</i> error (e.g., sign a contract).
            

Partners who want a <b>single URL</b> that walks the user through every pending
signing in one chain — instead of forwarding one URL per
`BusinessErrorApiDTO` — should use
SigningHandoff's `CombinedSigningUrl`.
The two are complementary: `SolutionUrl` is granular per-error;
`CombinedSigningUrl` is the chain-walking alternative for signing-related errors.

```json
{
  "error": null,
  "message": "Payment plan agreed with the debtor.",
  "businessErrors": [
    {
      "type": "string",
      "message": "Payment plan agreed with the debtor.",
      "solutionUrl": "https://app.debitura.com/…"
    }
  ]
}
```

<a id="check-if-a-client-can-be-deleted-test-environment-only"></a>

## Check if a client can be deleted (test environment only)

`GET /clients/{externalTenantId}/is-deletable`

Checks whether a client can be safely deleted for testing purposes.

⚠️ **TEST ENVIRONMENT ONLY** - This endpoint is only available on the test environment.

Use this endpoint before calling DELETE to verify the client can be removed.

A client can be deleted if:
- They have no active collection cases (only pending cases are allowed)
- They have no leads with active quotes

Returns
- **isDeletable**: true if the client can be deleted
- **blockers**: list of reasons why deletion is blocked (if any)

### Path parameters

- `externalTenantId` (string, required): 

### Response 200

Deletability check completed

- `isDeletable` (boolean): True if the client can be safely deleted.
- `blockers` (array of strings, nullable): List of reasons why the client cannot be deleted (empty if IsDeletable is true).

```json
{
  "isDeletable": true,
  "blockers": [
    "string"
  ]
}
```

### Response 403

Endpoint not available in production environment

- `error` (string, nullable): Short human-readable error label (legacy field — preserved for backward compatibility).
- `message` (string, nullable): Human-readable error description (legacy field — preserved for backward compatibility).
- `businessErrors` (array of objects, nullable): Canonical structured error array. Consumers should migrate to reading this field.
- `businessErrors[].type` (string, nullable): The type of business error (e.g., "MissingDebtCollectionContract", "MissingPowerOfAttorney", "NoPartnerAvailable").
- `businessErrors[].message` (string, nullable): A human-readable description of the error.
- `businessErrors[].solutionUrl` (string, nullable): A URL where the user can resolve this <i>specific</i> error (e.g., sign a contract).
            

Partners who want a <b>single URL</b> that walks the user through every pending
signing in one chain — instead of forwarding one URL per
`BusinessErrorApiDTO` — should use
SigningHandoff's `CombinedSigningUrl`.
The two are complementary: `SolutionUrl` is granular per-error;
`CombinedSigningUrl` is the chain-walking alternative for signing-related errors.

```json
{
  "error": null,
  "message": "Payment plan agreed with the debtor.",
  "businessErrors": [
    {
      "type": "string",
      "message": "Payment plan agreed with the debtor.",
      "solutionUrl": "https://app.debitura.com/…"
    }
  ]
}
```

### Response 404

No active client link found for this externalTenantId

- `error` (string, nullable): Short human-readable error label (legacy field — preserved for backward compatibility).
- `message` (string, nullable): Human-readable error description (legacy field — preserved for backward compatibility).
- `businessErrors` (array of objects, nullable): Canonical structured error array. Consumers should migrate to reading this field.
- `businessErrors[].type` (string, nullable): The type of business error (e.g., "MissingDebtCollectionContract", "MissingPowerOfAttorney", "NoPartnerAvailable").
- `businessErrors[].message` (string, nullable): A human-readable description of the error.
- `businessErrors[].solutionUrl` (string, nullable): A URL where the user can resolve this <i>specific</i> error (e.g., sign a contract).
            

Partners who want a <b>single URL</b> that walks the user through every pending
signing in one chain — instead of forwarding one URL per
`BusinessErrorApiDTO` — should use
SigningHandoff's `CombinedSigningUrl`.
The two are complementary: `SolutionUrl` is granular per-error;
`CombinedSigningUrl` is the chain-walking alternative for signing-related errors.

```json
{
  "error": null,
  "message": "Payment plan agreed with the debtor.",
  "businessErrors": [
    {
      "type": "string",
      "message": "Payment plan agreed with the debtor.",
      "solutionUrl": "https://app.debitura.com/…"
    }
  ]
}
```

### Response 500

Internal server error

- `error` (string, nullable): Short human-readable error label (legacy field — preserved for backward compatibility).
- `message` (string, nullable): Human-readable error description (legacy field — preserved for backward compatibility).
- `businessErrors` (array of objects, nullable): Canonical structured error array. Consumers should migrate to reading this field.
- `businessErrors[].type` (string, nullable): The type of business error (e.g., "MissingDebtCollectionContract", "MissingPowerOfAttorney", "NoPartnerAvailable").
- `businessErrors[].message` (string, nullable): A human-readable description of the error.
- `businessErrors[].solutionUrl` (string, nullable): A URL where the user can resolve this <i>specific</i> error (e.g., sign a contract).
            

Partners who want a <b>single URL</b> that walks the user through every pending
signing in one chain — instead of forwarding one URL per
`BusinessErrorApiDTO` — should use
SigningHandoff's `CombinedSigningUrl`.
The two are complementary: `SolutionUrl` is granular per-error;
`CombinedSigningUrl` is the chain-walking alternative for signing-related errors.

```json
{
  "error": null,
  "message": "Payment plan agreed with the debtor.",
  "businessErrors": [
    {
      "type": "string",
      "message": "Payment plan agreed with the debtor.",
      "solutionUrl": "https://app.debitura.com/…"
    }
  ]
}
```

<a id="withdraw-an-attributed-client"></a>

## Withdraw an attributed client

`POST /clients/{externalTenantId}/withdraw`

Withdraws a client that never completed onboarding. Archives the referral partner link and closes all pending cases with close code CaseNeverStartedInternal.

The same externalTenantId can be re-submitted via POST /clients after withdrawal.

Path Parameter
- **externalTenantId** - Your internal identifier for the client

Business Rules
- Only attributed clients (IsAttributedClient = true) can be withdrawn
- All cases for this client must be in PendingContractSigning status

What Happens
- The referral partner client link is archived
- All pending cases are closed with close code CaseNeverStartedInternal

What Does NOT Happen
- The client record itself is not deleted or anonymised. The company, its users, its KYC record
  and any signed agreements are all retained

After Withdrawal
- The same externalTenantId can be re-submitted via POST /clients
- Provided the re-submission still identifies the SAME client — that is, it carries a user email
  or supportEmail already registered on it — it re-links that original client rather than creating
  a second one: a new active link is established on the same Debitura client, attribution
  (IsAttributedClient=true) is preserved, and the archived link is kept for audit. The call returns
  201/202 as normal — not a 409
- Any cases in the re-submission are created against that client. A CreditorReference used by a
  case that this withdrawal closed can be reused, because such a case no longer reserves it
- Any approval request left pending for this externalTenantId is resolved as declined, since the
  link it was asking the client to approve now exists
- Re-submitting with entirely different contact emails does NOT re-link. 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 — so a new
  client is created, exactly as before this behaviour existed
- 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
- Re-linking only applies to your own withdrawn client. If the externalTenantId now resolves to a
  different client, or that client has since linked to another partner, the normal
  409 ClientExistsNeedsLinking / AlreadyLinkedToAnotherPartner handling applies unchanged

Error Cases
- **404 Not Found** - No active client link exists for this externalTenantId and your partner account
- **409 Conflict** - Client cannot be withdrawn because:
  - IsAttributedClient = false (non-attributed clients cannot be withdrawn)
  - One or more cases have progressed beyond PendingContractSigning

### Path parameters

- `externalTenantId` (string, required): 

### Response 204

Client withdrawn successfully

### Response 404

No active client link found for this externalTenantId

- `error` (string, nullable): Short human-readable error label (legacy field — preserved for backward compatibility).
- `message` (string, nullable): Human-readable error description (legacy field — preserved for backward compatibility).
- `businessErrors` (array of objects, nullable): Canonical structured error array. Consumers should migrate to reading this field.
- `businessErrors[].type` (string, nullable): The type of business error (e.g., "MissingDebtCollectionContract", "MissingPowerOfAttorney", "NoPartnerAvailable").
- `businessErrors[].message` (string, nullable): A human-readable description of the error.
- `businessErrors[].solutionUrl` (string, nullable): A URL where the user can resolve this <i>specific</i> error (e.g., sign a contract).
            

Partners who want a <b>single URL</b> that walks the user through every pending
signing in one chain — instead of forwarding one URL per
`BusinessErrorApiDTO` — should use
SigningHandoff's `CombinedSigningUrl`.
The two are complementary: `SolutionUrl` is granular per-error;
`CombinedSigningUrl` is the chain-walking alternative for signing-related errors.

```json
{
  "error": null,
  "message": "Payment plan agreed with the debtor.",
  "businessErrors": [
    {
      "type": "string",
      "message": "Payment plan agreed with the debtor.",
      "solutionUrl": "https://app.debitura.com/…"
    }
  ]
}
```

### Response 409

Cannot withdraw — client not attributed or cases have progressed beyond onboarding

- `error` (string, nullable): Short human-readable error label (legacy field — preserved for backward compatibility).
- `message` (string, nullable): Human-readable error description (legacy field — preserved for backward compatibility).
- `businessErrors` (array of objects, nullable): Canonical structured error array. Consumers should migrate to reading this field.
- `businessErrors[].type` (string, nullable): The type of business error (e.g., "MissingDebtCollectionContract", "MissingPowerOfAttorney", "NoPartnerAvailable").
- `businessErrors[].message` (string, nullable): A human-readable description of the error.
- `businessErrors[].solutionUrl` (string, nullable): A URL where the user can resolve this <i>specific</i> error (e.g., sign a contract).
            

Partners who want a <b>single URL</b> that walks the user through every pending
signing in one chain — instead of forwarding one URL per
`BusinessErrorApiDTO` — should use
SigningHandoff's `CombinedSigningUrl`.
The two are complementary: `SolutionUrl` is granular per-error;
`CombinedSigningUrl` is the chain-walking alternative for signing-related errors.

```json
{
  "error": null,
  "message": "Payment plan agreed with the debtor.",
  "businessErrors": [
    {
      "type": "string",
      "message": "Payment plan agreed with the debtor.",
      "solutionUrl": "https://app.debitura.com/…"
    }
  ]
}
```

### Response 500

Internal server error

- `error` (string, nullable): Short human-readable error label (legacy field — preserved for backward compatibility).
- `message` (string, nullable): Human-readable error description (legacy field — preserved for backward compatibility).
- `businessErrors` (array of objects, nullable): Canonical structured error array. Consumers should migrate to reading this field.
- `businessErrors[].type` (string, nullable): The type of business error (e.g., "MissingDebtCollectionContract", "MissingPowerOfAttorney", "NoPartnerAvailable").
- `businessErrors[].message` (string, nullable): A human-readable description of the error.
- `businessErrors[].solutionUrl` (string, nullable): A URL where the user can resolve this <i>specific</i> error (e.g., sign a contract).
            

Partners who want a <b>single URL</b> that walks the user through every pending
signing in one chain — instead of forwarding one URL per
`BusinessErrorApiDTO` — should use
SigningHandoff's `CombinedSigningUrl`.
The two are complementary: `SolutionUrl` is granular per-error;
`CombinedSigningUrl` is the chain-walking alternative for signing-related errors.

```json
{
  "error": null,
  "message": "Payment plan agreed with the debtor.",
  "businessErrors": [
    {
      "type": "string",
      "message": "Payment plan agreed with the debtor.",
      "solutionUrl": "https://app.debitura.com/…"
    }
  ]
}
```

<a id="submit-kyc-verification-for-a-client"></a>

## Submit KYC verification for a client

`POST /clients/{externalTenantId}/kyc-verification`

Submits KYC/AML director verification data for an existing client. Multiple submissions are allowed; the latest record is used for verification checks. When sendChatNotification is true (default), a system message is posted on all active cases for this client to notify the collection partner.

### Path parameters

- `externalTenantId` (string, required): 

### Query parameters

- `sendChatNotification` (boolean): 

### Headers

- `Idempotency-Key` (string): Optional non-empty, non-whitespace idempotency key (max 255 characters) for safely retrying this request. If a previous request used the same key with an identical body, the original terminal response is replayed verbatim. Reusing the key with a different body returns 422 with `businessErrors[0].type: "IdempotencyConflict"`. Field-level 400 validation errors are not stored, so you may fix the request and retry with the same key.
  Max 255 characters.

### Request body (application/json)

- `directorFullName` (string, required): 
  Max 500 characters.
- `directorHomeAddress` (string, required): 
  Max 1000 characters.
- `directorDateOfBirth` (date, required): 

```json
{
  "directorFullName": "Muster GmbH",
  "directorHomeAddress": "Friedrichstraße 68",
  "directorDateOfBirth": "2026-10-01"
}
```

### Response 201

KYC verification submitted

- `directorFullName` (string, nullable): 
- `directorHomeAddress` (string, nullable): 
- `directorDateOfBirth` (date): 
- `dateCreated` (datetime): 
- `verificationStatus` (enum, nullable): Partner/staff-set review status (Processing/Completed) for this submission. Null = not yet
reviewed. Note: distinct from the sibling `ClientResponse.KycStatus` field, which
describes whether KYC data has been submitted at all.
  Values: `Processing`, `Completed`, `null`.
- `verificationStatusUpdatedAt` (datetime, nullable): When VerificationStatus was last set. Null until set.

```json
{
  "directorFullName": "Muster GmbH",
  "directorHomeAddress": "Friedrichstraße 68",
  "directorDateOfBirth": "2026-10-01",
  "dateCreated": "2026-10-01T14:05:00Z",
  "verificationStatus": "Processing",
  "verificationStatusUpdatedAt": "2026-10-01T14:05:00Z"
}
```

### Response 404

Client not found

- `error` (string, nullable): Short human-readable error label (legacy field — preserved for backward compatibility).
- `message` (string, nullable): Human-readable error description (legacy field — preserved for backward compatibility).
- `businessErrors` (array of objects, nullable): Canonical structured error array. Consumers should migrate to reading this field.
- `businessErrors[].type` (string, nullable): The type of business error (e.g., "MissingDebtCollectionContract", "MissingPowerOfAttorney", "NoPartnerAvailable").
- `businessErrors[].message` (string, nullable): A human-readable description of the error.
- `businessErrors[].solutionUrl` (string, nullable): A URL where the user can resolve this <i>specific</i> error (e.g., sign a contract).
            

Partners who want a <b>single URL</b> that walks the user through every pending
signing in one chain — instead of forwarding one URL per
`BusinessErrorApiDTO` — should use
SigningHandoff's `CombinedSigningUrl`.
The two are complementary: `SolutionUrl` is granular per-error;
`CombinedSigningUrl` is the chain-walking alternative for signing-related errors.

```json
{
  "error": null,
  "message": "Payment plan agreed with the debtor.",
  "businessErrors": [
    {
      "type": "string",
      "message": "Payment plan agreed with the debtor.",
      "solutionUrl": "https://app.debitura.com/…"
    }
  ]
}
```

### Response 500

Internal server error

- `error` (string, nullable): Short human-readable error label (legacy field — preserved for backward compatibility).
- `message` (string, nullable): Human-readable error description (legacy field — preserved for backward compatibility).
- `businessErrors` (array of objects, nullable): Canonical structured error array. Consumers should migrate to reading this field.
- `businessErrors[].type` (string, nullable): The type of business error (e.g., "MissingDebtCollectionContract", "MissingPowerOfAttorney", "NoPartnerAvailable").
- `businessErrors[].message` (string, nullable): A human-readable description of the error.
- `businessErrors[].solutionUrl` (string, nullable): A URL where the user can resolve this <i>specific</i> error (e.g., sign a contract).
            

Partners who want a <b>single URL</b> that walks the user through every pending
signing in one chain — instead of forwarding one URL per
`BusinessErrorApiDTO` — should use
SigningHandoff's `CombinedSigningUrl`.
The two are complementary: `SolutionUrl` is granular per-error;
`CombinedSigningUrl` is the chain-walking alternative for signing-related errors.

```json
{
  "error": null,
  "message": "Payment plan agreed with the debtor.",
  "businessErrors": [
    {
      "type": "string",
      "message": "Payment plan agreed with the debtor.",
      "solutionUrl": "https://app.debitura.com/…"
    }
  ]
}
```
