Skip to main content

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)

ErrorCause
Request cannot be nullMissing or empty request body
At least one user is requiredusers array is null or empty
When multiple users provided, exactly one must have IsOnboardingUser=trueMultiple users, none marked as onboarding user
Only one user can be marked as IsOnboardingUserMultiple users have isOnboardingUser: true
Unknown country: XXclient.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)

ErrorCause
Invalid currency code: XYZcurrencyCode not recognized
Case date cannot be in the futuredate is a future date
Due date cannot be earlier than the case datedueDate is before date
Due date must be in the pastdueDate is today or in the future
Case total must be a positive amountamountToRecover is zero or negative
Debtor information is requireddebtor object is null
Invalid debtor typedebtor.type is not "Company" or "Private" (case-insensitive)
Invalid country code: ZZdebtor.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 debtorsUS debtor without debtor.stateAlpha2 or debtor.state
Collection partner not foundcollectionPartnerId override does not exist or is not active

Webhooks

ErrorCause
Model state errorsMissing url or events on POST /v1/webhooks
URL validation errorWebhook 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 messageCauseFix
API Key was not providedMissing XApiKey headerAdd XApiKey: YOUR_KEY to every request
Invalid API KeyKey not found in DebituraVerify key is correct and matches the environment (test vs production)
Invalid bearer tokenToken expired (30-min lifetime), revoked, or malformedMint 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:

404 Not Found

The requested resource does not exist or does not belong to your partner account.

EndpointTitleCommon cause
GET/DELETE /clients/{externalTenantId}Client Not FoundWrong externalTenantId, client archived, or belongs to another partner
POST /oauth/tokenClient Not FoundClient hasn't completed SDCA signing — check onboardingDone via GET /clients/{externalTenantId} first
GET /cases/{id}Case Not FoundCase does not exist or belongs to a client not linked to your partner account
GET/PUT/DELETE /v1/webhooks/{id}Webhook not foundWebhook 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.

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/..."
}
]
}
TypeCauseHas solutionUrlFix
MissingDebtCollectionContractSDCA not signed or needs re-signingYesPresent URL to client, retry after signing
MissingPowerOfAttorneyPoA (or JPA) not signed for this jurisdictionYesPresent URL to client, retry after signing
MissingKycVerificationCollection partner requires KYC and creditor hasn't completed itYesPresent URL to client, retry after completion. Not bypassed by allowPendingContracts.
NoPartnerAvailableNo collection partner covers this jurisdictionNoShow "not supported" message. Do not auto-retry.
CreditorBlockedCreditor account is blockedNoContact 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.