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. Field-validation errors are typically a JSON object keyed by field name with arrays of error strings. Value-level business validations return the structured ApiErrorResponseDto shape ({ error, message, businessErrors: [] }). Malformed JSON or type-mismatch errors from model binding return ASP.NET ProblemDetails.

{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"errors": {
"Users": ["At least one user is required"]
},
"traceId": "..."
}

Client Onboarding (POST /clients)​

ErrorCause
RFC 7807 validation responseMissing, empty, malformed, or type-invalid request body; [ApiController] handles this before the action runs
At least one user is requiredusers array is empty (a null users array returns The Users field is required.)
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
Field-keyed object with Cases[n].Field keys (e.g. {"Cases[0].DueDate": ["..."]})Cases included in the request have invalid fields; client creation is aborted. Annotation-level case errors arrive inside the Validation Problem Details errors object instead.

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 strictly in the future (tomorrow or later) — today is accepted
Case total must be a positive amountamountToRecover is zero or negative
Validation Problem Details errors.Debtor: The Debtor field is required.debtor is explicitly null
Invalid debtor type – allowed values are 'Company' or 'Private' (case-insensitive)debtor.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

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)
'<type>' is not a valid referral partner event type. Valid types: ...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, cases.replay_failed
caseId is required for <type> events.Case event test trigger without caseId
externalTenantId is required for <type> events.Client event test trigger without externalTenantId

The controller-level POST /v1/webhooks/test validations above return the standard ApiErrorResponseDto / businessErrors shape. Data-annotation and model-binding failures are intercepted earlier by [ApiController] and return Validation Problem Details instead.

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)
Token has expired, Token has been revoked, or a token-validation detailToken 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.

{
"error": "This endpoint is only available in the test environment. Use testreferral-api.debitura.com for testing.",
"message": "This endpoint is only available in the test environment. Use testreferral-api.debitura.com for testing.",
"businessErrors": [
{
"type": "ValidationError",
"message": "This endpoint is only available in the test environment. Use testreferral-api.debitura.com for testing.",
"solutionUrl": ""
}
]
}

These endpoints return ApiErrorResponseDto, not Problem Details. The reset-client and webhook-test messages include the test host shown above; the deletability check uses the shorter sentence without the host suffix.

Affected endpoints:

404 Not Found​

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

EndpointApiErrorResponseDto type/messageCommon cause
GET/DELETE /clients/{externalTenantId}NotFound with an endpoint-specific messageWrong externalTenantId, client archived, or belongs to another partner
POST /oauth/tokenNotFound: No linked client was found for the supplied tenant.No active link for this externalTenantId — the client was never created, or the link was archived/withdrawn. A token is minted as soon as a non-deleted, non-archived link exists; SDCA does not need to be signed first.
GET /cases/{id}CaseNotFound with a case-scoped messageCase does not exist or belongs to a client not linked to your partner account
GET/PUT/DELETE /v1/webhooks/{id}WebhookNotFound: Webhook not foundWebhook does not exist or belongs to a different partner — list webhooks via GET /v1/webhooks to find valid IDs

These responses use error, message, and businessErrors; they do not include a Problem Details title field.

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 missing SDCA or PoA can place a case in PendingContractSigning rather than returning a contract-related 422. KYC is evaluated separately and does not itself set that lifecycle on this replay path. There is no case.failed event. A replayed case that fails is never created, so it has no lifecycle; each failure is reported by a cases.replay_failed webhook (creditorReference, failureReason). Cases whose creditorReference already exists for the link are skipped silently. 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​

InvalidClientType is defined in the conflict-type enum but is not currently returned. A non-creditor account (e.g. a collection-partner user) is never matched by client detection. If its email is submitted as a user email, the request fails with 409 UserCreationFailed; if only the supportEmail matches, a new client is created. 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 HTTP 409 with ApiErrorResponseDto when withdrawal is blocked — either because isAttributedClient is false, or cases have progressed beyond PendingContractSigning.

{
"error": "The client cannot be withdrawn. Withdrawal is only allowed for clients your organisation brought to Debitura, and only while all of their cases are still in onboarding.",
"message": "The client cannot be withdrawn. Withdrawal is only allowed for clients your organisation brought to Debitura, and only while all of their cases are still in onboarding.",
"businessErrors": [
{
"type": "Conflict",
"message": "The client cannot be withdrawn. Withdrawal is only allowed for clients your organisation brought to Debitura, and only while all of their cases are still in onboarding.",
"solutionUrl": ""
}
]
}

422 Unprocessable Entity​

Business rule violations. The request is valid but cannot be processed due to domain constraints.

Response format: Two shapes are currently reachable. Orchestrator errors use a typed businessErrors array with type, message, and solutionUrl. Earlier business-rule checks can instead return a field-keyed dictionary with no businessErrors array. Detect the shape before reading it.

{
"businessErrors": [
{
"type": "MissingPowerOfAttorney",
"message": "Power of attorney not signed with partner X.",
"solutionUrl": "https://referral.debitura.com/PowerOfAttorney/Sign/..."
}
]
}

For example, the no-partner pre-check uses the legacy shape:

{
"BusinessRule": ["We don't have an exclusive pre‑legal partner in the provided jurisdiction"]
}
Typed businessErrors[].typeCausesolutionUrlFix
MissingDebtCollectionContractSDCA not signed or needs re-signingYesPresent URL to client, retry after signing
MissingPowerOfAttorneyPoA (or JPA for a jurisdiction pricing zone) 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.
CreditorBlockedCreditor account is blockedPresent as an empty stringContact Debitura support. Error message includes the reason.
CollectionPartnerNotFoundcollectionPartnerId override is unknown or deleted. Message: Collection partner {GUID} not found; the legacy CollectionPartnerId key carries the same message alongsideNoOmit the override or use a valid collection partner ID

NoPartnerAvailable remains an internal enum value, but POST /cases does not emit it in businessErrors[].type: the reachable no-match path is the field-keyed BusinessRule response shown above.

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.