Error Reference

Every error the UrbanPayX API can return, what causes it, and how to resolve it.

Error Reference

This page documents every error the UrbanPayX API can return, what causes it, and how to resolve it.


Error response formats

The API uses two error response formats depending on the context:

Standard format — used by most endpoints:

{
  "detail": "Human-readable error message"
}

Validation format — returned by FastAPI for request body schema violations (422):

{
  "detail": [
    {
      "loc": ["body", "field_name"],
      "msg": "description of what's wrong",
      "type": "error type"
    }
  ]
}

The HTTP status code is always present in the response header. Use the status code to determine the error category, then read the detail field for specifics.


HTTP status codes at a glance

CodeMeaningWhen you'll see it
400Bad RequestBusiness rule violation, invalid state transition, or configuration error
401UnauthorizedInvalid/expired token, wrong credentials, or revoked session
403ForbiddenYour role doesn't have permission, or a feature is disabled for your account
404Not FoundResource doesn't exist or doesn't belong to your client
409ConflictIdempotency key reuse with different payload, or resource state conflict
422Validation ErrorRequest body doesn't match the expected schema
429Too Many RequestsRate limit exceeded — wait before retrying
500Internal Server ErrorSomething went wrong on our side
502Bad GatewayUpstream service (email delivery) failed
503Service UnavailableA dependent service is down or not configured

400 — Bad Request

These errors indicate your request is structurally valid but violates a business rule or attempts an impossible operation.

Authentication & accounts

Error messageCauseFix
Invalid API key or secretAPI credentials are wrongDouble-check your api_key and api_secret. If you rotated keys, use the new ones.
Invalid refresh tokenRefresh token is malformed or expiredRe-authenticate with login or API key. Refresh tokens expire after 30 days.
Current token is not a dashboard account tokenUsing an API token for a dashboard-only operationUse email/password login instead of API key auth for this endpoint.
New password must be different from current passwordPassword change uses the same passwordChoose a different password.
Current password is incorrectWrong current password during password changeVerify the current password.
Refresh token does not belong to current access tokenMismatched token pairUse the refresh token that was issued alongside your current access token.

MFA configuration

Error messageCauseFix
Cannot enable TOTP before enrolling an authenticator appTrying to enable TOTP without setupComplete TOTP enrollment first via POST /auth/mfa/totp/enroll.
When account MFA is enabled, at least one method must be enabledDisabling the last MFA method while MFA is onEither keep one method enabled, or disable MFA entirely.
Account primary MFA method is totp but totp MFA is disabledSetting primary to TOTP while TOTP is offEnable TOTP first, then set it as primary.
TOTP enrollment challenge is invalid or expiredEnrollment confirmation too lateStart a new enrollment with POST /auth/mfa/totp/enroll.
Invalid authenticator codeWrong TOTP codeCheck the code in your authenticator app. Codes refresh every 30 seconds.

Team accounts

Error messageCauseFix
Client account email already existsDuplicate team member emailUse a different email address.
Cannot delete the last active ownerDeleting the only OWNER accountPromote another account to OWNER first.
Cannot deactivate or demote the last active ownerRemoving the last OWNER roleEnsure another active OWNER exists before changing this account.
Cannot delete the currently logged-in accountSelf-deletion attemptLog in as a different account to delete this one.

OpCo (Operating Company)

Error messageCauseFix
Opco is in status and can no longer be editedEditing a non-DRAFT OpCoOpCos can only be edited in DRAFT status. Create a new one if needed.
Opco status is not DRAFT. Only DRAFT opco can be submitted againSubmitting a non-DRAFT OpCoOnly OpCos in DRAFT status can be submitted.
Opco cannot be bound to a project when rejected or deactivatedLinking a REJECTED/DEACTIVATED OpCo to a projectUse an ACTIVATED OpCo. If rejected, create and submit a new one.
Target opco belongs to a different clientReferencing another client OpCoUse an OpCo ID that belongs to your client.
Opco_type cannot be nullMissing OpCo type in requestSpecify opco_type as licensed_tpp_sole_trader or licensed_tpp_non_sole_trader_private.

OpCo validation (by type)

Error messageCauseFix
Sole_trader is required for licensed_tpp_sole_traderMissing sole trader detailsInclude the sole_trader object with fullName, address, and dateOfBirth.
UBOs is required for licensed_tpp_non_sole_trader_privateMissing UBO detailsInclude the ubos array for non-sole-trader OpCos.
Directors is required for licensed_tpp_non_sole_trader_privateMissing director detailsInclude the directors array.
Signatories is required for licensed_tpp_non_sole_trader_privateMissing signatory detailsInclude the signatories array.

Transactions & payments

Error messageCauseFix
Callback URL is not setNo callback URL configuredSet your callback_url via PUT /auth/client/settings before generating payment links.
Transaction in terminal status cannot be refreshedRefreshing a terminal transactionOnly pending and processing transactions can be refreshed.
Transaction has no upstream payment id, cannot refreshTransaction was not fully createdThe payment provider did not return a payment ID. Contact support.
X-Idempotency-Key must not be emptyEmpty idempotency headerProvide a non-empty value for the X-Idempotency-Key header.
Opco does not have a valid Sub-TPP IDOpCo not fully set upSubmit the OpCo and wait for activation before creating transactions.

Webhooks

Error messageCauseFix
Webhook_url is required when webhook is enabledEnabling webhooks without a URLSet webhook_url before enabling webhook delivery.
Webhook_url is required before sending a test eventTesting without a webhook URLConfigure your webhook_url first.
Event_types must contain at least one eventEmpty event types arrayInclude at least one event type (e.g., payment.status_changed).
Invalid JSON payloadMalformed request bodyEnsure your request body is valid JSON.

Support tickets

Error messageCauseFix
Closed tickets cannot receive new client repliesReplying to a closed ticketOpen a new ticket if you need further assistance.
Closed tickets must be reopened before replyingSame as aboveCreate a new ticket instead.
Only resolved tickets can be closed by the clientClosing a non-resolved ticketWait for the ticket to be marked as resolved, then close it.

401 — Unauthorized

These errors mean authentication failed. Your token is missing, expired, revoked, or the credentials are wrong.

Error messageCauseFix
Could not validate credentialsToken is missing, malformed, or expiredInclude a valid Authorization: Bearer <token> header. If expired, refresh it.
Token has been revokedThe token was explicitly revoked (logout)Re-authenticate to get a new token.
Incorrect email or passwordWrong login credentialsCheck email and password. After 5 failed attempts, you will be locked out for 5 minutes.
Invalid API key or secretWrong API credentialsVerify your API key and secret. If you rotated them, use the new ones.
Client is not activeAccount is deactivatedContact support to reactivate your account.
Client account is not activeTeam member account is deactivatedAsk an OWNER to reactivate your account.
Invalid OTP challenge payloadExpired or wrong MFA challenge tokenRequest a new challenge and complete verification promptly.

All 401 responses include a WWW-Authenticate: Bearer header.


403 — Forbidden

You are authenticated, but your role does not have permission for this action, or a feature is disabled.

Error messageCauseFix
Insufficient permissions for this actionYour role cannot perform this operationCheck the Roles and Permissions matrix. API key tokens have the operations role.
This action requires a dashboard account tokenUsing API key auth for a dashboard-only operationAuthenticate via email/password login instead.
Payment link generation is disabled for this clientFeature gated for your accountContact support to enable payment link generation.
KYC link generation is disabled for this clientFeature gated for your accountContact support to enable KYC link generation.
Project is frozen by adminProject has been frozenContact support to understand why the project was frozen.
Production access is disabled for this clientYour account is not yet enabled for the production environmentUse the sandbox environment, or contact support to enable production access.
Client is not activated yet. Please verify email firstEmail verification not completeComplete the email verification step from registration.
Client registration is not allowed, please contact supportSelf-registration is disabledContact the UrbanPayX team to get an account provisioned.

404 — Not Found

The resource does not exist, or it belongs to a different client (the API intentionally does not distinguish between these for security).

Error messageCauseFix
Opco not foundInvalid OpCo IDVerify the OpCo ID. List your OpCos with GET /opcos.
Project not foundInvalid project IDVerify the project ID. List your projects with GET /projects.
Transaction not foundInvalid transaction IDVerify the transaction ID. List transactions with GET /transactions.
User not foundInvalid user IDVerify the user ID. List users with GET /kyc/users.
User not found, please create user and complete required verification firstTrying to generate a payment link for a non-existent userCreate the user via POST /kyc/users and verify them before generating a payment link.
Account not foundTeam account ID is invalidList team accounts with GET /auth/team-accounts.
Ticket not foundSupport ticket ID is invalidList tickets with GET /tickets.
Invoice not foundBilling invoice ID is invalidList invoices with GET /billing/invoices.

409 — Conflict

The request conflicts with the current state of a resource.

Error messageCauseFix
Idempotency key already used with a different request payloadSame X-Idempotency-Key but different bodyUse a new idempotency key for each distinct payment.
Duplicated request with same idempotency key is still being processedConcurrent request with the same keyWait for the first request to complete, then retry.
Transaction is already in terminal status and cannot start a new checkoutRe-initiating a completed transactionCreate a new transaction for a new payment.
Project has dependent transactionsDeleting a project with transactionsAdd cascade=true to the request, or resolve the transactions first.
User has dependent transactionsDeleting a user with transactionsAdd cascade=true to the request, or resolve the transactions first.

422 — Validation Error

The request body does not match the expected schema. FastAPI auto-generates these from the Pydantic models.

{
  "detail": [
    {
      "loc": ["body", "amount"],
      "msg": "ensure this value is greater than 0",
      "type": "value_error.number.not_gt"
    }
  ]
}

Common causes: missing required fields, wrong data types, invalid email format, amount less than or equal to zero, currency not exactly 3 characters. Read the loc field to identify which field failed, and msg for what went wrong.


429 — Too Many Requests

You have hit a rate limit. Wait before retrying.

Error messageCauseFix
Too many login attempts5+ failed login attemptsWait the indicated time. Lockout is per-email, lasts 300 seconds.
Please wait before refreshing this transaction againTransaction refresh cooldownUse webhooks instead of polling, or respect the cooldown.

Tip: For transaction status, prefer webhooks over polling. Configure your webhook_url and listen for payment.status_changed events.


500 — Internal Server Error

Something went wrong on our side. These should be rare.

Error messageCauseFix
Failed to initiate paymentPayment provider communication failedRetry after a brief wait. If persistent, contact support.
Failed to create user, please retryUser creation failed unexpectedlyRetry the request.
Failed to initialize user for KYC, please retryKYC provider setup failedRetry. If persistent, contact support.
Failed to initiate KYC, please retry laterKYC provider is not respondingWait and retry.

If you consistently see 500 errors, please contact support with the request details (endpoint, payload, timestamp).


502 — Bad Gateway

An upstream service (typically email delivery) failed.

ContextFix
Team member creation or credential deliveryThe team member was likely created, but the email was not delivered. Check the team accounts list and resend credentials manually if needed.

503 — Service Unavailable

A required service is down or not configured.

Error messageCauseFix
Email delivery failed. Please retry later or contact support.Email provider is unreachableRetry after a brief wait.

Common troubleshooting scenarios

I am getting 403 on Generate Payment Link
Your token has the developer role, which cannot generate payment links. Use an OWNER or OPERATIONS token. If you are using API key auth, this should not happen since API keys default to OPERATIONS.

OpCo must be ACTIVATED
Your OpCo is still in DRAFT or AWAITING_APPROVAL. Submit it with POST /opcos/{opco_id}/submit and wait for activation. In sandbox, this takes minutes.

User not found when generating a payment link
The user needs to exist and be verified before you can create a payment. Create the user with POST /kyc/users, initiate verification with POST /kyc/verify, and wait for kyc_status to reach approved.

Idempotency key already used with a different request payload
You are reusing an X-Idempotency-Key from a previous request but the body has changed (different amount, user, etc.). Generate a new unique key for each distinct payment intent.

Callback URL is not set
You need to configure a callback URL before generating payment links. This is where users get redirected after checkout. Set it with PUT /auth/client/settings.

Could not validate credentials on every request
Check that your Authorization header is formatted correctly: Bearer <token> (with a space, no quotes around the token). Access tokens expire after 2 hours (API key) or 30 minutes (dashboard login) — refresh or re-authenticate if expired.