---
title: "Create and onboard a new client"
method: POST
path: "/clients"
tags: ["Clients"]
---

# 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:** The `POST /clients` endpoint is idempotent and re-checks SDCA status on every call.
   This means 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)**
   There are TWO distinct 409 conflict scenarios - check the ConflictResponse.Type field to distinguish:

   **2a. ClientExistsNeedsLinking** (Type: "ClientExistsNeedsLinking")
   - Client already exists in Debitura (matched by user email or support email)
   - A link request is created with an expiration window configured per-partner (`ApprovalTtlDays`, default 7 days, clamped 1–30)
   - Existing client must approve the referral partner link via OnboardingLinks.Url
   - If approved, IsAttributedClient will be FALSE (revenue only on partner-referred cases)
   - Cases submitted in the original request are persisted and replayed against the linked creditor automatically when the user approves. `AllowPendingContracts=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: "AlreadyLinkedToAnotherPartner")
   - Client is already linked to a DIFFERENT referral partner
   - Only one referral partner link per client is supported
   - Cannot proceed - contact Debitura support for resolution
   - Returns 409 with error message and support contact

3. **Idempotency**
   - Repeated calls with same ExternalTenantId return existing client status (201 or 202)
   - No duplicate clients or links are created

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)
- **409 Conflict** - Two scenarios (check ConflictResponse.Type):
  - "ClientExistsNeedsLinking" - Client exists, needs approval link (if approved, IsAttributedClient=false)
  - "AlreadyLinkedToAnotherPartner" - Client already linked to different partner (cannot proceed)
- **422 Unprocessable Entity** - Business rule violation (field validation errors only, NOT partner matching failures)
- **500 Internal Server Error** - Unexpected server error

Optional Multi-Case Creation
If the Cases array is provided in the request:
- ALL cases are validated BEFORE client creation (checks field validation and duplicate references)
- Client is ALWAYS created to ensure referral partner link and future attribution
- Cases with available collection partners are created successfully (CaseResults.SuccessfulCases)
- Cases without available partners are NOT created and reported as failures (CaseResults.FailedCases)
- If validation errors exist (primitives, duplicates), client creation is aborted and 400 is returned
- Successful cases appear in CaseResults.SuccessfulCases with full case details
- Failed cases appear in CaseResults.FailedCases with CaseIndex, CreditorReference, and error details (e.g., "No collection partner available for jurisdiction")

User Roles
- **IsOnboardingUser=true** - User receives CreditorAdmin role (full access)
- **IsOnboardingUser=false** - User receives CreditorUser role (limited access)

Revenue Sharing (Fee Percentage Locked at Link Creation)
- The referral fee percentage is snapshot from the partner's current configuration at the exact moment the client link is created
- **This percentage is IMMUTABLE and will NEVER change for this client** - even if the partner's global fee percentage is updated later
- The locked percentage is used for ALL revenue calculations for ALL cases created by this client, forever
- This ensures predictable, stable revenue sharing and prevents disputes over retroactive fee changes
- To see the locked percentage for a specific client, use GET /clients/{externalTenantId} (included in response)

## Request body

- DebituraWebReferralPartnerApiModelsClientsCreateClientRequest
  - `externalTenantId` string, required
  - `client` DebituraWebReferralPartnerApiModelsClientsClientDetailsDto, required
    - `name` string, required
    - `registrationNumber` string, nullable
    - `address` string, nullable
    - `zipCode` string, nullable
    - `city` string, nullable
    - `state` string, nullable
    - `country` string, required
    - `supportEmail` string, email, required
    - `supportPhone` string, nullable
  - `users` DebituraWebReferralPartnerApiModelsClientsClientUserDto[], required
    - `name` string, required
    - `email` string, email, required
    - `isOnboardingUser` boolean — Marks this user as the one going through onboarding. Defaults to false. Exactly ONE user must have this set to true.
  - `cases` DebituraWebExternalApiContractsV1CasesRequestsCreateCollectionCaseRequestApiViewModel[], 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).
    - `currencyCode` string, nullable, required
    - `date` string, date-time
    - `dueDate` string, date-time, nullable
    - `comments` string, nullable — Optional comments about the case, e.g. payment history or communication context.
    - `claimDescription` string, nullable — Client provided description of the claim
    - `creditorReference` string, nullable
    - `debtor` DebituraWebExternalApiContractsV1CasesDebtorDto — V1 Debtor DTO for external partner APIs. The debtor is the party that owes the debt.
      - `type` string, required — Debtor type. Valid values: "Company" or "Person"
      - `name` string, required — Debtor name (company name or person's full name)
      - `contactPerson` string, nullable — Contact person at the company (required for companies, not used for persons)
      - `companyRegistrationNumber` string, nullable — Company registration number (VAT number, CVR, org number, etc.)
      - `address` string, nullable — Street address
      - `zipCode` string, nullable — Postal/ZIP code
      - `city` string, nullable — City name
      - `state` string, nullable — State/region/province name
      - `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")
      - `countryAlpha2` string, nullable — Country code (ISO 3166-1 alpha-2 format)
      - `country` string, nullable — Country name
      - `email` string, nullable — Email address for debtor contact
      - `phone` string, nullable — Phone number (include country code)
    - `creditorDivisionId` string, uuid, nullable
    - `amountToRecover` number, double — 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).
    - `amountToRecoverOver6Months` number, double, 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
    - `amountToRecoverOver12Months` number, double, 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
    - `amountToRecoverOver24Months` number, double, 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
    - `skipDebituraVerification` boolean — This skips the 'Pending verification' for Debitura and puts case straight to partner
    - `skipCreationEmails` boolean — Deprecated — this field is accepted for backwards compatibility but is ignored server-side. Creation emails are always suppressed; the hourly CasesStarted digest is the single notification channel for all entry points.
    - `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).
    - `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.
    - `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.
    - `collectionPartnerId` string, uuid, nullable — Optional: Specify a collection partner ID to handle this case. When provided, this partner will be used regardless of lead agent matching rules. The partner must be active and have coverage for the debtor's jurisdiction.
    - `assignedUserEmail` string, email, 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.
    - `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.

## Response `201`

Client created and fully onboarded (terms signed)

- DebituraWebReferralPartnerApiModelsClientsClientCreatedResponse
  - `externalTenantId` string, nullable
  - `onboardingDone` boolean
  - `onboardingLinks` DebituraWebReferralPartnerApiModelsClientsOnboardingLinksDto
    - `url` string, nullable
  - `client` DebituraWebReferralPartnerApiModelsClientsCreditorDto
    - `id` string, uuid
    - `companyName` string, nullable
    - `officeEmail` string, nullable
    - `country` string, nullable
    - `address` string, nullable
    - `city` string, nullable
    - `zipCode` string, nullable
    - `companyRegistrationNumber` string, nullable
  - `users` DebituraWebReferralPartnerApiModelsClientsUserDto[], nullable
    - `id` integer
    - `email` string, nullable
    - `firstName` string, nullable
    - `lastName` string, nullable
  - `isAttributedClient` boolean
  - `dateLinked` string, date-time
  - `caseStats` DebituraWebReferralPartnerApiModelsClientsClientCaseStats
    - `casesTotal` integer
    - `casesClosed` integer
    - `earningsUsd` number, double
  - `kycStatus` 'NotRequired' | 'Pending' | 'Verified' — KYC (Know Your Customer) verification status for a client linked to a referral partner. Captures three distinct states that a simple boolean cannot express. Wire format is LOCKED to snake_case string values ("not_required", "pending", "verified") via Newtonsoft.Json StringEnumConverter with SnakeCaseNamingStrategy. The host serializer for this API is Newtonsoft.Json (AddNewtonsoftJson in Program.cs), so a System.Text.Json JsonStringEnumConverter attribute would be silently ignored — hence the explicit Newtonsoft converter here. The System.Text.Json JsonConverter attribute is declared in addition so that consumers (and our own integration tests) who parse responses using System.Text.Json can deserialize the string form back into this enum. The Newtonsoft converter is what actually controls outbound wire format on this host.
  - `kycVerification` DebituraWebReferralPartnerApiModelsClientsKycVerificationDto
    - `directorFullName` string, nullable
    - `directorHomeAddress` string, nullable
    - `directorDateOfBirth` string, date
    - `dateCreated` string, date-time
    - `verificationStatus` 'Processing' | 'Completed' — Partner/staff-settable review status for a Debitura.Domain.Model.Creditors.CreditorKycVerifications.CreditorKycVerification record. Distinct from the ReferralPartnerApi `KycStatus` enum, which describes whether a client has submitted KYC data at all — this enum describes whether data that has already been submitted has since been reviewed by the collection partner or Debitura staff. The unset/not-yet-reviewed state is represented by a null Debitura.Domain.Model.Creditors.CreditorKycVerifications.CreditorKycVerification.VerificationStatus column, not a third enum value here. A fresh KYC resubmission (a new row via `CreditorKycVerificationService.CreateAsync`) naturally leaves this column unset, resetting review status by design. Wire format is locked to named string values ("Processing", "Completed") via Newtonsoft.Json StringEnumConverter — every host this enum is exposed on (CollectionPartnerApi, CoreApi, ReferralPartnerApi) uses Newtonsoft (AddNewtonsoftJson in Program.cs), so a System.Text.Json JsonStringEnumConverter attribute alone would be silently ignored; both are declared so STJ-based consumers (and our own tests) can also deserialize the string form.
    - `verificationStatusUpdatedAt` string, date-time, nullable — When Debitura.Web.ReferralPartnerApi.Models.Clients.KycVerificationDto.VerificationStatus was last set. Null until set.
  - `caseResults` DebituraWebReferralPartnerApiModelsClientsMultiCaseResult — Result of creating multiple cases during client creation. Groups successful and failed case creation attempts.
    - `successfulCases` DebituraWebExternalApiContractsV1CasesInvoiceDto[], nullable — Cases that were created successfully. Each element contains the full case details.
      - `id` string, uuid
      - `dateCreated` string, date-time
      - `dateUpdated` string, date-time, nullable
      - `reference` string, nullable
      - `creditorReference` string, nullable
      - `creditorComments` string, nullable
      - `claimDescription` string, nullable
      - `grossAmount` number, double
      - `remainder` number, double
      - `interestFees` number, double
      - `reminderFees` number, double
      - `collectionFees` number, double
      - `totalAddedFees` number, double
      - `currency` string, nullable
      - `isTestCase` boolean
      - `lifecycle` string, nullable
      - `dueDate` string, date-time
      - `date` string, date-time
      - `dateFinished` string, date-time, nullable
      - `dateCollectionStarted` string, date-time, nullable
      - `closeCode` string, nullable
      - `currentEngagementPhase` string, nullable — The current phase of the case's engagement: "Pre-legal", "Legal", or "Enforcement". A different axis from Debitura.Web.ExternalApi.Contracts.V1.Cases.InvoiceDto.Lifecycle/Debitura.Web.ExternalApi.Contracts.V1.Cases.InvoiceDto.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.
      - `claimType` string, nullable — The type of claim for this case (e.g. "Unpaid Invoice", "Loan Repayment", "Breach of Contract"). Null if not set.
      - `creditorDivisionId` string, uuid, nullable
      - `debtor` DebituraWebExternalApiContractsV1CasesDebtorDto — V1 Debtor DTO for external partner APIs. The debtor is the party that owes the debt.
        - `type` string, required — Debtor type. Valid values: "Company" or "Person"
        - `name` string, required — Debtor name (company name or person's full name)
        - `contactPerson` string, nullable — Contact person at the company (required for companies, not used for persons)
        - `companyRegistrationNumber` string, nullable — Company registration number (VAT number, CVR, org number, etc.)
        - `address` string, nullable — Street address
        - `zipCode` string, nullable — Postal/ZIP code
        - `city` string, nullable — City name
        - `state` string, nullable — State/region/province name
        - `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")
        - `countryAlpha2` string, nullable — Country code (ISO 3166-1 alpha-2 format)
        - `country` string, nullable — Country name
        - `email` string, nullable — Email address for debtor contact
        - `phone` string, nullable — Phone number (include country code)
      - `collectionPartner` DebituraWebExternalApiContractsV1CasesCollectionPartnerDto — V1 Collection Partner DTO for external partner APIs
        - `name` string, nullable
        - `officeEmail` string, nullable
        - `officePhone` string, nullable
        - `publicSite` string, nullable
        - `surveyCadenceMode` 0 | 1 — Controls which surveys are generated for cases assigned to this collection partner.
      - `creditor` DebituraWebExternalApiContractsV1CasesCreditorDto — Creditor (client) information for external partner APIs. Represents the party that the debtor owes money to.
        - `id` string, uuid — Unique identifier for the creditor
        - `companyName` string, nullable — Company name of the creditor
        - `companyRegistrationNumber` string, nullable — Company registration number (CVR, VAT number, etc.)
        - `officeEmail` string, nullable — Primary office email address
        - `officePhone` string, nullable — Primary office phone number
        - `address` string, nullable — Street address
        - `city` string, nullable — City
        - `zipCode` string, nullable — Postal/ZIP code
        - `state` string, nullable — State or region (if applicable)
        - `country` string, nullable — Country name
        - `division` DebituraWebExternalApiContractsV1CasesCreditorDivisionDto — Creditor division information for external partner APIs. Represents a specific division or department within a creditor organization.
          - `id` string, uuid — Unique identifier for the division
          - `name` string, nullable — Name of the division
      - `bankAccount` DebituraWebExternalApiContractsV1CasesBankAccountDto — 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)
        - `id` integer — Bank account identifier
        - `label` string, nullable — User-friendly label (e.g., "Main EUR Account")
        - `scheme` string, nullable — Account scheme: IBAN, SWIFT, or LOCAL
        - `currencyCode` string, nullable — Currency code (ISO 4217)
        - `bankCountryCode` string, nullable — Bank country code (ISO Alpha-2)
        - `accountHolderName` string, nullable — Account holder name (beneficiary)
        - `iban` string, nullable — IBAN (for IBAN scheme accounts)
        - `bic` string, nullable — BIC/SWIFT code (for IBAN and SWIFT scheme accounts)
        - `accountNumber` string, nullable — Account number (for SWIFT and LOCAL scheme accounts)
        - `localIdentifier` string, nullable — Local identifier (for LOCAL scheme accounts, e.g., sort code + account number)
        - `localIdentifierType` string, nullable — Type of local identifier (e.g., "Sort Code", "Routing Number")
        - `bankName` string, nullable — Bank name (optional)
        - `bankAddress` string, nullable — Bank address (optional)
        - `bankCity` string, nullable — Bank city (optional)
        - `bankZipCode` string, nullable — Bank zip/postal code (optional)
        - `bankState` string, nullable — Bank state/region (optional)
      - `blendedAgeUpliftPoints` number, double, 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).
      - `preLegalSuccessFee` number, double, 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.
      - `solutionUrl` string, nullable — 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.
      - `signingHandoff` DebituraWebExternalApiContractsV1CasesSigningHandoffDto — 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.
        - `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.
      - `exclusivePeriodEndDate` string, date-time, 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.
      - `disputeStatus` string, nullable — Whether the claim is disputed by the debtor. Returns the description of Debitura.Domain.Model.Receiveables.Invoices.Enums.ClaimDisputeStatus: "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.
      - `validation` DebituraDomainServicesCaseValidationCaseValidationLeanDto — Lean validation summary exposed on list endpoints of the External Customer API and Collection Partner API. Contains only Debitura.Domain.Services.CaseValidation.CaseValidationLeanDto.NeedsInfo — no join required. Derived purely from free Debitura.Domain.Model.Receiveables.Invoices.Invoice columns. When Debitura.Domain.Services.CaseValidation.CaseValidationLeanDto.NeedsInfo is `true`, callers should invoke `GET /cases/{id}/validation` to retrieve the full item-level breakdown (Debitura.Domain.Services.CaseValidation.CaseValidationStatusDto).
        - `needsInfo` boolean — True when the latest validation run requires creditor action. Reads Debitura.Domain.Model.Receiveables.Invoices.Invoice.ValidationNeedsInfo directly.
      - `assignedUser` DebituraWebExternalApiContractsV1CasesAssignedUserDto — Represents the creditor team member assigned to a case.
        - `email` string, nullable — The assigned user's email address.
        - `name` string, nullable — The assigned user's full name.
      - `allocationOutstanding` DebituraWebExternalApiContractsV1CasesInvoiceAllocationOutstandingDto — Additive external-API read model. Per-bucket outstanding on the debt ledger, produced by the payment allocation engine (bucket total minus Σ active stored allocations — never re-derived from a model). Mirrors the internal `Debitura.Domain.Model.Receiveables.InvoiceEconomics.EconomicalAllocationOutstanding` shape.
        - `principal` number, double
        - `interest` number, double
        - `reminderFees` number, double
        - `collectionFees` number, double
    - `failedCases` DebituraWebReferralPartnerApiModelsClientsCaseCreationFailure[], nullable — Cases that failed during creation. Each element contains error details and the original case index.
      - `caseIndex` integer — Zero-based index of the failed case in the original Cases array.
      - `creditorReference` string, nullable — Creditor reference from the failed case, if provided. Helps consumers identify which specific case failed.
      - `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>Debitura.Web.ReferralPartnerApi.Models.Clients.CaseCreationErrorTypes.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>Debitura.Web.ReferralPartnerApi.Models.Clients.CaseCreationErrorTypes.ValidationError</term><description>The request failed field-level validation. Check the Debitura.Web.ReferralPartnerApi.Models.Clients.CaseCreationFailure.ValidationErrors property for detailed field-specific errors. Common causes: missing required fields, invalid formats, business rule violations.</description></item><item><term>Debitura.Web.ReferralPartnerApi.Models.Clients.CaseCreationErrorTypes.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>Debitura.Web.ReferralPartnerApi.Models.Clients.CaseCreationErrorTypes.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>Debitura.Web.ReferralPartnerApi.Models.Clients.CaseCreationErrorTypes.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.
      - `errorMessage` string, nullable — High-level error message explaining why the case creation failed.
      - `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).
      - `signingHandoff` DebituraWebExternalApiContractsV1CasesSigningHandoffDto — 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.
        - `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.

## Other responses

- `202` — Client created but onboarding incomplete (use OnboardingLinks.Url to complete)
- `400` — Invalid request (validation errors)
- `409` — Client already exists - approval required to link (use OnboardingLinks.Url for approval)
- `422` — Business rule violation (field validation errors only)
- `500` — Internal server error

---

[API](https://skmtc.net/debitura/apis/debitura-referral-partner-api.md) · [All operations](https://skmtc.net/debitura/apis/debitura-referral-partner-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/debitura/debitura-referral-partner-api/revisions/abf2adee265f/schema)
