Error Reference
Every error a referral partner integration can encounter, organized by HTTP status code.
For the standard error response format and retry strategy, see Error Handling. For symptom-based debugging, see Troubleshooting.
400 Bad Request
Validation failures. The request body or query parameters are invalid. Fix the input and retry.
Response format: Varies by endpoint — typically a JSON object where keys are field names and values are arrays of error strings. Some endpoints (e.g. webhook test triggers) return RFC 7807 Problem Details instead.
{
"Users": ["At least one user is required"]
}
Client Onboarding (POST /clients)
| Error | Cause |
|---|---|
Request cannot be null | Missing or empty request body |
At least one user is required | users array is null or empty |
When multiple users provided, exactly one must have IsOnboardingUser=true | Multiple users, none marked as onboarding user |
Only one user can be marked as IsOnboardingUser | Multiple users have isOnboardingUser: true |
Unknown country: XX | client.country is not a valid ISO 3166-1 alpha-2 code or country name |
Case validation failed (with validationErrors object) | Cases included in the request have invalid fields — check each Cases[n].Field key |
Case Submission (POST /cases)
| Error | Cause |
|---|---|
Invalid currency code: XYZ | currencyCode not recognized |
Case date cannot be in the future | date is a future date |
Due date cannot be earlier than the case date | dueDate is before date |
Due date must be in the past | dueDate is today or in the future |
Case total must be a positive amount | amountToRecover is zero or negative |
Debtor information is required | debtor object is null |
Invalid debtor type | debtor.type is not "Company" or "Private" (case-insensitive) |
Invalid country code: ZZ | debtor.countryAlpha2 is not a valid ISO alpha-2 code. If using debtor.country (name), the error message will suggest using countryAlpha2 instead. |
A state code ... is required for US debtors | US debtor without debtor.stateAlpha2 or debtor.state |
Collection partner not found | collectionPartnerId override does not exist or is not active |
Webhooks
| Error | Cause |
|---|---|
| Model state errors | Missing url or events on POST /v1/webhooks |
| URL validation error | Webhook URL is HTTP, localhost, private IP, or uses a non-standard port (only 443/8443 allowed) |
Invalid Event Type (Problem Details) | Unknown event type on POST /v1/webhooks/test. Valid types: case.created, case.updated, case.closed, client.onboarding.poa_signed, client.onboarding.contract_signed, client.linked, client.link_declined, client.link_requested, client.link_expired |
Missing CaseId (Problem Details) | Case event test trigger without caseId |
Missing ExternalTenantId (Problem Details) | Client event test trigger without externalTenantId |
401 Unauthorized
Authentication failed. Check your credentials and environment.
Response format: RFC 7807 Problem Details.
{
"title": "Unauthorized",
"detail": "API Key was not provided",
"status": 401
}
| Detail message | Cause | Fix |
|---|---|---|
API Key was not provided | Missing XApiKey header | Add XApiKey: YOUR_KEY to every request |
Invalid API Key | Key not found in Debitura | Verify key is correct and matches the environment (test vs production) |
Invalid bearer token | Token expired (30-min lifetime), revoked, or malformed | Mint a fresh token via POST /oauth/token. See the retry-on-401 pattern. |
403 Forbidden
Test-only endpoints called against production.
{
"title": "Forbidden",
"detail": "This endpoint is only available in the test environment.",
"status": 403
}
Affected endpoints:
DELETE /clients/{externalTenantId}— reset test clientsGET /clients/{externalTenantId}/is-deletablePOST /v1/webhooks/test— webhook testing
404 Not Found
The requested resource does not exist or does not belong to your partner account.
| Endpoint | Title | Common cause |
|---|---|---|
GET/DELETE /clients/{externalTenantId} | Client Not Found | Wrong externalTenantId, client archived, or belongs to another partner |
POST /oauth/token | Client Not Found | Client hasn't completed SDCA signing — check onboardingDone via GET /clients/{externalTenantId} first |
GET /cases/{id} | Case Not Found | Case does not exist or belongs to a client not linked to your partner account |
GET/PUT/DELETE /v1/webhooks/{id} | Webhook not found | Webhook belongs to a different partner — list webhooks via GET /v1/webhooks to find valid IDs |
409 Conflict
A conflict with existing state. Each conflict type requires different handling.
Response format: type, message, and optional data payload.
ClientExistsNeedsLinking
The email matches an existing Debitura account. Present data.onboardingLinks.url to the user for approval. Approval URLs expire after a configurable per-partner TTL (ApprovalTtlDays, default 7 days, clamped 1–30 days). Subscribe to client.link_expired to detect expiry; resubmit POST /clients with the same externalTenantId to generate a fresh approval URL.
Cases submitted in the original request are persisted server-side and replayed against the matched creditor automatically once the user approves the link. AllowPendingContracts=true is forced on replay regardless of what you sent on the original request, so cases land in PendingContractSigning lifecycle state rather than 422-failing on missing SDCA/PoA/KYC. There is no case.failed webhook on this path — detect failures via the case lifecycle field. See Handling 409 Conflicts for the full flow.
{
"type": "ClientExistsNeedsLinking",
"message": "Client already exists in Debitura. Approval required to link to referral partner.",
"data": {
"externalTenantId": "your-tenant-id",
"onboardingLinks": {
"url": "https://app.debitura.com/ReferralPartner/Approve?token=..."
}
}
}
For privacy, the 409 response does not reveal any details about the user's matched Debitura account — externalTenantId and onboardingLinks.url are the only fields you need to act on. The response also includes client, users, and isAttributedClient for JSON-shape stability with the success response — do not rely on them being populated on this conflict path.
ClientAlreadyLinkedToAnotherPartner
The client has an active link to a different referral partner. Only one partner per creditor. Contact partnerships@debitura.com.
InvalidClientType
The matched Debitura account is not a creditor — for example, it's a collection partner. Contact partnerships@debitura.com to resolve. See Handling 409 Conflicts.
Approve / decline race (link request already processed)
Concurrent attempts to approve or decline the same link request return 409 Conflict (atomic claim). Only the first caller succeeds; subsequent callers should treat the conflict as "already processed." This typically appears as a user double-clicking the approval button or two browser tabs racing the same approval URL — your integration does not need to retry.
Withdrawal Not Allowed
POST /clients/{externalTenantId}/withdraw returns Problem Details (not the type/message format above) when withdrawal is blocked — either because isAttributedClient is false, or cases have progressed beyond PendingContractSigning.
{
"title": "Withdrawal Not Allowed",
"detail": "...",
"status": 409
}
422 Unprocessable Entity
Business rule violations. The request is valid but cannot be processed due to domain constraints.
Response format: businessErrors array with type, message, and optional solutionUrl.
{
"businessErrors": [
{
"type": "MissingPowerOfAttorney",
"message": "Power of attorney not signed with partner X.",
"solutionUrl": "https://referral.debitura.com/PowerOfAttorney/Sign/..."
}
]
}
| Type | Cause | Has solutionUrl | Fix |
|---|---|---|---|
MissingDebtCollectionContract | SDCA not signed or needs re-signing | Yes | Present URL to client, retry after signing |
MissingPowerOfAttorney | PoA (or JPA) not signed for this jurisdiction | Yes | Present URL to client, retry after signing |
MissingKycVerification | Collection partner requires KYC and creditor hasn't completed it | Yes | Present URL to client, retry after completion. Not bypassed by allowPendingContracts. |
NoPartnerAvailable | No collection partner covers this jurisdiction | No | Show "not supported" message. Do not auto-retry. |
CreditorBlocked | Creditor account is blocked | No | Contact Debitura support. Error message includes the reason. |
:::warning MissingKycVerification is a hard block
Unlike contract-related errors, allowPendingContracts: true does not bypass MissingKycVerification. KYC is always enforced when submitting via bearer token. See KYC Verification.
:::
429 Too Many Requests
Rate limit exceeded. Read retryAfter from the response body and wait.
{
"error": "rate_limit_exceeded",
"message": "Too many requests. Please try again later or contact support if you need higher limits.",
"retryAfter": 42.0
}
Limits per API key: 2,000 requests/minute, 20,000/hour, 100,000/day. See Rate Limiting.
500 Internal Server Error
Transient server error. Retry with exponential backoff (max 3 retries). If persistent, contact partnerships@debitura.com with the request details and timestamp.