diff --git a/development-guide/api-errors/codes.mdx b/development-guide/api-errors/codes.mdx
index d86bb3a6..45faacd0 100644
--- a/development-guide/api-errors/codes.mdx
+++ b/development-guide/api-errors/codes.mdx
@@ -21,22 +21,23 @@ Every error response from the Nevermined API carries a stable `code` (e.g. `BCK.
- [`BCK.ACCOUNT_PROVISIONING`](#bck-account_provisioning) — 2 codes
- [`BCK.AGENT`](#bck-agent) — 12 codes
- [`BCK.APIKEY`](#bck-apikey) — 18 codes
-- [`BCK.AUTH`](#bck-auth) — 15 codes
+- [`BCK.ARD`](#bck-ard) — 1 code
+- [`BCK.AUTH`](#bck-auth) — 16 codes
- [`BCK.BILLING`](#bck-billing) — 18 codes
-- [`BCK.BRAINTREE`](#bck-braintree) — 10 codes
+- [`BCK.BRAINTREE`](#bck-braintree) — 13 codes
- [`BCK.BUDGETS`](#bck-budgets) — 6 codes
-- [`BCK.CATALOG`](#bck-catalog) — 3 codes
+- [`BCK.CATALOG`](#bck-catalog) — 9 codes
- [`BCK.COMMON`](#bck-common) — 34 codes
- [`BCK.CREDITS`](#bck-credits) — 6 codes
-- [`BCK.DELEGATION`](#bck-delegation) — 8 codes
-- [`BCK.ENTITLEMENTS`](#bck-entitlements) — 2 codes
+- [`BCK.DELEGATION`](#bck-delegation) — 9 codes
+- [`BCK.ENTITLEMENTS`](#bck-entitlements) — 3 codes
- [`BCK.GROUPS`](#bck-groups) — 12 codes
- [`BCK.GUEST`](#bck-guest) — 2 codes
- [`BCK.INVITATIONS`](#bck-invitations) — 5 codes
- [`BCK.LEGAL_DOCS`](#bck-legal_docs) — 6 codes
- [`BCK.METRIC`](#bck-metric) — 5 codes
- [`BCK.METRICS`](#bck-metrics) — 1 code
-- [`BCK.MPP`](#bck-mpp) — 5 codes
+- [`BCK.MPP`](#bck-mpp) — 6 codes
- [`BCK.NOTIF`](#bck-notif) — 9 codes
- [`BCK.OAUTH`](#bck-oauth) — 30 codes
- [`BCK.OBSERVABILITY`](#bck-observability) — 5 codes
@@ -47,12 +48,12 @@ Every error response from the Nevermined API carries a stable `code` (e.g. `BCK.
- [`BCK.PAYPAL`](#bck-paypal) — 1 code
- [`BCK.PLANS`](#bck-plans) — 1 code
- [`BCK.POINT`](#bck-point) — 19 codes
-- [`BCK.PROTOCOL`](#bck-protocol) — 57 codes
-- [`BCK.ROUTER`](#bck-router) — 11 codes
-- [`BCK.STRIPE`](#bck-stripe) — 34 codes
+- [`BCK.PROTOCOL`](#bck-protocol) — 60 codes
+- [`BCK.ROUTER`](#bck-router) — 13 codes
+- [`BCK.STRIPE`](#bck-stripe) — 36 codes
- [`BCK.STRIPE.CONNECT`](#bck-stripe-connect) — 8 codes
- [`BCK.TRANSCODING`](#bck-transcoding) — 4 codes
-- [`BCK.TXS`](#bck-txs) — 13 codes
+- [`BCK.TXS`](#bck-txs) — 16 codes
- [`BCK.USER_PROFILE`](#bck-user_profile) — 4 codes
- [`BCK.VERSION`](#bck-version) — 2 codes
- [`BCK.VGS`](#bck-vgs) — 5 codes
@@ -60,7 +61,7 @@ Every error response from the Nevermined API carries a stable `code` (e.g. `BCK.
- [`BCK.WIDGET`](#bck-widget) — 5 codes
- [`BCK.WIDGET_KEYS`](#bck-widget_keys) — 2 codes
- [`BCK.WIDGET_SESSION`](#bck-widget_session) — 13 codes
-- [`BCK.X402`](#bck-x402) — 53 codes
+- [`BCK.X402`](#bck-x402) — 56 codes
## `BCK.ACCOUNT_PROVISIONING`
@@ -109,6 +110,12 @@ Every error response from the Nevermined API carries a stable `code` (e.g. `BCK.
| `BCK.APIKEY.0018` | 400 | validation | — | Authenticated but no wallet linked to the account | Link a wallet to your account before registering an API key. Email/social sign-ins must add a wallet first. |
| `BCK.APIKEY.0019` | 500 | internal | — | Unexpected failure minting the API key | Minting failed server-side. Common causes: a pending DB migration on a freshly-deployed image, or a Privy/ZeroDev outage while deriving the account. Retry; if it persists, quote the correlation id. |
+## `BCK.ARD`
+
+| Code | HTTP | Category | Retryable | Message | Hint |
+|---|---|---|---|---|---|
+| `BCK.ARD.0001` | 400 | validation | ❌ | Invalid ARD request argument | An ARD `/search`, `/explore` or `/agents` argument was rejected — e.g. an unsupported `filter`/facet term, a malformed EBNF `filter` or `orderBy`, or an invalid value (`query.text`, `updatedAt`, a non-string filter value). The specific cause is in the response `details`. Supported filter/facet terms: type, tags, capabilities, publisher, pay:protocol, pay:currency, pay:network, pay:price (ARD §5.3.1). |
+
## `BCK.AUTH`
| Code | HTTP | Category | Retryable | Message | Hint |
@@ -128,6 +135,7 @@ Every error response from the Nevermined API carries a stable `code` (e.g. `BCK.
| `BCK.AUTH.0013` | 403 | internal | ❌ | Role guard active without @Roles metadata | A route was decorated with `@UseGuards(RolesGuard)` but no `@Roles(...)` declaration. The guard fails closed: no role list means no caller can satisfy the requirement. Add `@Roles(...)` to the handler or remove the `RolesGuard` wiring. |
| `BCK.AUTH.0014` | 503 | integration | ✅ | Identity provider temporarily unavailable — could not verify the session | The Privy identity-token verification (`users().get({ id_token })`) could not reach Privy (rate-limited after the SDK retries, a 5xx, or a network/timeout). This is transient and does NOT mean the session is invalid — retry after a short backoff. If it persists, check the Privy status page and the service's identity-provider configuration. |
| `BCK.AUTH.0015` | 401 | auth | — | Authentication required | Attach a valid `Authorization: Bearer ` (a Nevermined API key or a Privy identity token) and retry. |
+| `BCK.AUTH.0016` | 403 | auth | ❌ | Server-to-server operation not authorized | This endpoint requires a valid ops-token header (an `X-Ops-*` shared secret matching the deployment env var). It is server-to-server only — a browser preflight strips the header. See the exception details for the specific header/env var expected. |
## `BCK.BILLING`
@@ -162,10 +170,13 @@ Every error response from the Nevermined API carries a stable `code` (e.g. `BCK.
| `BCK.BRAINTREE.0004` | 400 | integration | — | Plan owner has not connected a Braintree merchant account | The plan owner has not connected Braintree. They must complete OAuth on the seller dashboard before their plans can be sold via Braintree. |
| `BCK.BRAINTREE.0005` | 400 | integration | — | Plan is not a fiat plan — cannot be purchased via Braintree | Use Braintree only for fiat plans. Crypto plans must be paid through the on-chain flow. |
| `BCK.BRAINTREE.0006` | 409 | integration | — | Plan owner has no Braintree merchant account connected | The plan owner has revoked or never connected their Braintree account. Ask them to reconnect before retrying the purchase. |
-| `BCK.BRAINTREE.0007` | 400 | integration | — | Plan owner's Braintree account does not have a merchant account in the plan's currency | Ask the seller to add a Braintree merchant account in the plan’s currency, then disconnect and reconnect to refresh the cached account list. |
-| `BCK.BRAINTREE.0008` | 400 | integration | — | Cannot create a Braintree plan in this currency: your Braintree account has no merchant account in that currency. Add one in your Braintree dashboard, then disconnect and reconnect to refresh. | Add a merchant account in the requested currency in the Braintree dashboard, then disconnect and reconnect to refresh. |
+| `BCK.BRAINTREE.0007` | 400 | integration | — | Plan owner's Braintree account has no active merchant account in the plan's currency | No active Braintree merchant account was found for the plan’s currency: commonly the seller has none in that currency and must add one, or has one that is suspended or pending rather than active — a suspended account has to be resolved with Braintree, while a pending one activates on its own. Either way the seller must then reconnect Braintree (disconnect, then connect again) for the cached account list to be rebuilt. |
+| `BCK.BRAINTREE.0008` | 400 | integration | — | Cannot create a Braintree plan in this currency: no active Braintree merchant account was found for you in that currency. If you have not connected Braintree, start there; otherwise add a merchant account in that currency, or check whether the one you have is suspended or pending, then reconnect Braintree to refresh. | You will also see this if you have never connected Braintree, so confirm the connection first. If it is connected, look in the Braintree dashboard for a merchant account in the requested currency: add one if there is none; if there is one it is commonly suspended or pending — a suspended account has to be resolved with Braintree, while a pending one activates on its own. Once it is active, reconnect Braintree (disconnect, then connect again) so the cached account list is rebuilt. |
| `BCK.BRAINTREE.0009` | 400 | integration | — | Plan metadata is missing currency. Plans must specify a currency to be settled via Braintree. | Re-publish the plan with metadata.currency populated. Braintree cannot route the settlement without a target currency. |
| `BCK.BRAINTREE.0010` | 503 | integration | ✅ | Braintree/PayPal payment provider is not available in this environment | Set `BRAINTREE_MERCHANT_ID`, `BRAINTREE_PUBLIC_KEY`, and `BRAINTREE_PRIVATE_KEY` in the deployment env. Returns 503 because the route is reachable only after the operator wires Braintree up. |
+| `BCK.BRAINTREE.0011` | 400 | integration | — | The connected Braintree account has no merchant account that can receive payments, so the connection was refused | Every merchant account on the Braintree account is either not active or has no active processor connection. Activate one in the Braintree control panel, then connect again. Nothing was stored on our side, so our record of any previous connection is unchanged. |
+| `BCK.BRAINTREE.0012` | 503 | integration | ✅ | Could not verify the connected Braintree account’s merchant accounts, so the connection was refused | Listing the merchant accounts failed transiently (network, timeout, rate limit or a Braintree outage), so we cannot confirm the account can receive payments. Connect again. Nothing was stored on our side, so our record of any previous connection is unchanged. |
+| `BCK.BRAINTREE.0013` | 502 | integration | ❌ | Braintree permanently refused to list the merchant accounts, so the connection was refused | Braintree rejected the request outright (authentication, authorization, not found or upgrade required) rather than failing transiently, so retrying will not help. Seller: disconnect and connect again from the dashboard to re-authorize. Operator: if every seller hits this, the OAuth application has most likely lost the `merchant_account:all` scope. Nothing was stored on our side. |
## `BCK.BUDGETS`
@@ -185,6 +196,12 @@ Every error response from the Nevermined API carries a stable `code` (e.g. `BCK.
| `BCK.CATALOG.0001` | 404 | business | ❌ | Agent service not found | No listed catalog service matches that slug. Slugs are case-sensitive; unlisted services are not exposed. |
| `BCK.CATALOG.0002` | 500 | internal | ✅ | Failed to read the agent services catalog | Transient server-side error reading the catalog (list, detail, or categories); safe to retry. Query inputs are validated upstream, so this is not a bad-request issue. |
| `BCK.CATALOG.0003` | 400 | validation | ❌ | Invalid catalog filter | The `protocol` filter must be one of: x402, mpp, rest, a2a, other. |
+| `BCK.CATALOG.0004` | 404 | business | ❌ | Agent not found | No agent with that DID belongs to your organization. You can only publish agents your organization owns. |
+| `BCK.CATALOG.0006` | 409 | business | ❌ | Agent is already listed in the catalog | This agent already has a catalog listing. Edit or remove the existing listing instead of publishing it again. |
+| `BCK.CATALOG.0007` | 404 | business | ❌ | Catalog listing not found | No catalog listing with that id belongs to your organization. |
+| `BCK.CATALOG.0008` | 500 | internal | ✅ | Failed to write the catalog listing | Transient server-side error creating or updating the listing; safe to retry. |
+| `BCK.CATALOG.0009` | 409 | business | ❌ | Listing is not in a re-submittable state | Only an unlisted listing (validation failed or removed) can be re-submitted. A live or degraded listing is still publicly listed (re-submitting would unlist it until the next probe), and a pending one is already being validated. |
+| `BCK.CATALOG.0010` | 403 | business | ❌ | Listing is under moderation hold | A Nevermined moderator unlisted this listing. It cannot be re-submitted or re-validated by the owner — contact Nevermined support to have it reviewed. |
## `BCK.COMMON`
@@ -248,6 +265,7 @@ Every error response from the Nevermined API carries a stable `code` (e.g. `BCK.
| `BCK.DELEGATION.0006` | 422 | business | ❌ | Plan payment provider is not network-token capable | A `provider: "vgs"` delegation is plan-agnostic and settles through the plan’s `fiatPaymentProvider`, resolved at CHARGE time (#2082) — but that plan’s provider is not in the network-token-capable acquirer set (currently stripe, braintree). The plan metadata likely carries an unexpected/unsupported `fiatPaymentProvider`. Fix the plan’s payment provider, then retry. |
| `BCK.DELEGATION.0007` | 400 | business | ❌ | Requested provider does not match the stored payment method | The create-delegation request declared a `provider` that does not match the provider the referenced payment method was enrolled under (e.g. requesting `stripe` for a card enrolled via the unified VGS-Collect rail, whose provider is `vgs`). Send the `provider` that matches the payment method — the value the delegation payment-methods list returns for it. |
| `BCK.DELEGATION.0008` | 422 | business | ❌ | Delegation cannot be settled via card | This delegation was created on the crypto (`erc4337`) rail, which settles on-chain and has no card payment provider — a `nvm:card-delegation` settle cannot charge it (#2627). Settle a crypto delegation through the `nvm:erc4337` scheme instead, or create a card delegation (stripe/braintree/visa/vgs) for card settlement. |
+| `BCK.DELEGATION.0009` | 400 | validation | ❌ | delegationId must be a v4 UUID | The `delegationId` path parameter must be a v4 UUID (e.g. a1b2c3d4-e5f6-4a90-8bcd-ef1234567890). This is a request-format error, not an authentication or not-found failure — a well-formed but unknown id returns 404 instead. |
## `BCK.ENTITLEMENTS`
@@ -255,6 +273,7 @@ Every error response from the Nevermined API carries a stable `code` (e.g. `BCK.
|---|---|---|---|---|---|
| `BCK.ENTITLEMENTS.0001` | 403 | business | ❌ | Resource cap reached for your current workspace. Upgrade to unlock higher limits. | The active workspace (personal or Premium org) has hit its agent/plan cap. Response `params.cap` and `params.current` carry the limit and current count; switch workspaces, deactivate unused resources, or upgrade the org tier to lift the cap. |
| `BCK.ENTITLEMENTS.0002` | 403 | business | ❌ | Organization is not active. Reactivate the subscription before creating new resources. | The target workspace has a lapsed subscription (paid period ended without renewal, or admin override). Existing resources remain visible but new agents/plans cannot be registered until the org is reactivated via the Billing page. |
+| `BCK.ENTITLEMENTS.0003` | 403 | business | ❌ | PayPal/Braintree settlement requires a Premium or Enterprise organization. | PayPal/Braintree settlement is available only to Premium or Enterprise organization workspaces. This is enforced both when linking a Braintree merchant account and when publishing a Braintree plan. Connect or publish under a paid organization workspace, choose Stripe or stablecoin settlement, or upgrade the organization on the Billing page. |
## `BCK.GROUPS`
@@ -326,6 +345,7 @@ Every error response from the Nevermined API carries a stable `code` (e.g. `BCK.
| `BCK.MPP.0003` | 402 | business | — | Invalid payment credential | The credential did not verify. Request a fresh challenge and present a new credential. The reason is deliberately not disclosed — reporting which check failed would let a caller forge one iteratively. |
| `BCK.MPP.0004` | 402 | business | — | Payment challenge expired | Challenges are short-lived. Re-request the protected resource to obtain a fresh 402 challenge and present a credential against that one. |
| `BCK.MPP.0005` | 402 | business | — | Request body does not match the payment challenge | The challenge is bound to a digest of the request body. Send the exact body the challenge was issued for, or request a new challenge for the body you intend to send. |
+| `BCK.MPP.0006` | 500 | internal | — | Could not mint the MPP payment challenge | The challenge could not be built. Retry; if it persists this is a server-side fault and the correlation id in this response identifies it in the logs. |
## `BCK.NOTIF`
@@ -373,7 +393,7 @@ Every error response from the Nevermined API carries a stable `code` (e.g. `BCK.
| `BCK.OAUTH.0026` | 400 | auth | ❌ | Account-level authorization requires funding details | An account-level connect is delegation-backed: it must carry the spend cap it binds to — `provider`, `provider_payment_method_id`, `spending_limit_cents`, `duration_secs`, and `currency`. Enrol a card and set a cap before authorizing. #2541. |
| `BCK.OAUTH.0027` | 403 | auth | ❌ | This credential cannot create authorizations or spend mandates | An `account_access` credential is minted to SPEND against the card delegation it is bound to (via x402), NOT to run a new authorization ceremony or create another card mandate. It could otherwise mint itself a second, larger mandate on the same card, defeating the consented cap. Authorize from the human browser session, or use an agent-specific key for agent flows. #2574 B1. |
| `BCK.OAUTH.0029` | 500 | internal | ❌ | Internal error creating the agent binding | A server-side data-integrity condition — an agent-specific (credits_purchase) binding reached persistence without an agent id, which the database CHECK forbids. No action is required from the caller; inspect the API logs (the failing authorization request id is on the error `details`/`params`). #2578. |
-| `BCK.OAUTH.0030` | 403 | auth | ❌ | This credential cannot use the Router spend rails or create delegations | An OAuth-minted credential (`credits_purchase` or `account_access`) may not call `POST /router/{payments,route,proxy}` or `POST /delegation/create`: those routes sign from the account wallet, outside the session-key policy the credential advertises — and a `credits_purchase` key owns no delegation, so any delegation it reaches was never consented for. Use a plain API key from the account owner, or the credential’s own x402 spend rail. #2575. |
+| `BCK.OAUTH.0030` | 403 | auth | ❌ | This credential cannot use the Router spend rails or create delegations | An OAuth-minted credential (`credits_purchase` or `account_access`) may not call `POST /router/{payments,route,proxy}` or `POST /delegation/create`: those routes sign from the account wallet, outside the session-key policy the credential advertises — and a `credits_purchase` key owns no delegation, so any delegation it reaches was never consented for. Use a plain API key from the account owner, or the credential’s own x402 spend rail. |
| `BCK.OAUTH.0031` | 400 | auth | ❌ | Invalid client metadata document | The `client_id` was treated as a CIMD (Client ID Metadata Document) URL but did not resolve to a valid document. It must be an https URL on a public host that returns a JSON document whose `client_id` equals the URL and which declares a non-empty `client_name` and `redirect_uris`. If your host uses static registration instead, register it out-of-band and use its issued `client_id`. |
## `BCK.OBSERVABILITY`
@@ -555,13 +575,16 @@ Every error response from the Nevermined API carries a stable `code` (e.g. `BCK.
| `BCK.PROTOCOL.0055` | 404 | validation | ❌ | Payment plan does not exist on-chain | The request references a planId that is not registered on the settlement network, so the on-chain call reverted with PlanNotFound. Check the planId (it is a uint256 decimal string, not a DID) and that it was created on the SAME network you are writing to. `GET /api/v1/protocol/plans/{planId}` confirms whether it exists (#2163). |
| `BCK.PROTOCOL.0056` | 409 | business | ❌ | This plan can only be purchased once per account, and you already own it | The plan installs the one-time-purchase hook (OneTimeCreatorHook), which allows a single agreement per (plan, buyer). Your account has already ordered it, so the on-chain call reverted with CreatorAlreadyCreatedAgreement. Nothing was charged. Use the credits you already hold, or order a different plan (#2164). |
| `BCK.PROTOCOL.0057` | 400 | validation | ❌ | A value in the request could not be encoded for the on-chain call | An address or numeric value in the payload is malformed, so the call could not even be encoded — most commonly a token/receiver address whose EIP-55 checksum is wrong (mixed-case addresses are checksum-verified). Send the address all-lowercase, or with a correct checksum. `params.detail` names the offending value (#2478). |
+| `BCK.PROTOCOL.0058` | 500 | integration | ❌ | Payment plan is registered in our records but not on the settlement network | This is a server-side inconsistency, not a problem with your request: the plan exists in our records but is not registered on the settlement network. It usually means a plan registration did not fully land. Contact support with the planId; retrying the link will not help until the plan is (re)registered on chain. |
+| `BCK.PROTOCOL.0059` | 500 | integration | ❌ | The blockchain transaction relayer is temporarily rate-limited | The blockchain transaction relayer (AA bundler / RPC provider) is temporarily rate-limited, so the on-chain operation did not complete — this is a transient upstream throttle, not a bug in your request or a contract revert. Retry manually after a short backoff. If it persists, the relayer's rate-limit quota is likely exhausted and needs raising. |
+| `BCK.PROTOCOL.0060` | 500 | integration | ❌ | The blockchain transaction relayer timed out | The blockchain transaction relayer (AA bundler / RPC provider) timed out, so the on-chain operation did not complete in time — this is a transient upstream timeout, not a bug in your request or a contract revert. Wait a short backoff before retrying, and check whether the operation eventually landed before re-submitting (the write is not idempotent). If it persists, the relayer/RPC endpoint is likely overloaded or misconfigured. |
## `BCK.ROUTER`
| Code | HTTP | Category | Retryable | Message | Hint |
|---|---|---|---|---|---|
| `BCK.ROUTER.0001` | 400 | validation | ❌ | Invalid Router payment request | Bad input to the Router: unsupported `protocol`, a malformed/empty `target` (no `accepts`), no fundable option for the funded networks/assets, an upstream pay-to outside the delegation’s allowed recipients, a non-crypto (non-erc4337) delegation, or a missing `delegationId`. The per-failure `details` names the specific problem. |
-| `BCK.ROUTER.0002` | 409 | business | ❌ | requestId already used | This `requestId` already minted a credential (idempotency). Omit it or use a fresh value — one credential per requestId. |
+| `BCK.ROUTER.0002` | 409 | business | ❌ | requestId already used | This `requestId` already minted a credential — that is idempotency working, not an error to route around. If this is a RETRY of the same purchase, reuse the same `requestId` and take the original `paymentId` from `params`. Use a fresh id only for a genuinely DIFFERENT purchase: it mints a second credential and is charged the routing fee again. |
| `BCK.ROUTER.0003` | 402 | business | ❌ | Delegation budget exceeded, expired, or inactive | The spend would exceed the delegation cap, or the delegation is expired / exhausted / revoked. Create or top up a delegation via POST /api/v1/delegation/create. |
| `BCK.ROUTER.0004` | 404 | business | ❌ | Router payment not found | No Router payment with that id belongs to the authenticated user. |
| `BCK.ROUTER.0005` | 409 | business | ❌ | Router payment is not in a settleable state | Only an Issued payment can be marked Settled. Re-reporting the same txHash on an already-Settled payment is a no-op; a different txHash, or a non-Issued state, is rejected. |
@@ -569,8 +592,10 @@ Every error response from the Nevermined API carries a stable `code` (e.g. `BCK.
| `BCK.ROUTER.0007` | 429 | business | ✅ | Too many concurrent routed requests | You have too many in-flight mode-B routed requests (/route, /proxy) open at once. Let some complete before starting more, or slow the request rate. |
| `BCK.ROUTER.0008` | 403 | business | ❌ | Router requires an EIP-7702 (v2) API key | This is a legacy (v1) API key bound to the old smart account, which cannot sign EIP-3009 from the unified funded wallet. Create a new API key — it will be issued as v2 (EIP-7702) and works with the Router. Existing v1 keys keep working for credit-based (nvm:erc4337) flows until they expire. |
| `BCK.ROUTER.0009` | 402 | business | ❌ | Insufficient wallet balance to fund the payment | The funding source could not cover this charge. **On the crypto rails** (x402 / MPP-tempo, which pull from the wallet's own balance — the router never holds funds) the buyer's custodial wallet does not hold enough of the payment asset on the target network: fund the wallet on the target chain and retry. **On the card rail** (MPP-stripe) the card issuer declined the charge: use a different card or contact the issuer — there is no wallet to top up, so ignore the on-chain advice above. In both cases this is distinct from the delegation cap (BCK.ROUTER.0003), which authorizes the spend but does not provide the funds, and from a card that needs 3-D Secure authentication (BCK.ROUTER.0011), where the card is fine and merely unauthenticated. |
-| `BCK.ROUTER.0010` | 500 | internal | ❌ | Router could not determine the amount to charge against the delegation cap | The payment handler reported a settlement amount in cents that is not a non-negative integer, so the routing-fee arithmetic (#2191) cannot compute what to reserve. This is an internal invariant violation, not a bad request — the value is produced by Nevermined, not the caller. It deliberately fails rather than defaulting to zero, which would reserve nothing and let the payment through free. DO NOT BLIND-RETRY: no budget was reserved and no payment record was written, but a payment credential WAS already minted (on the card rail, a Stripe Shared Payment Token that will auto-expire). Because no record exists, your requestId will not suppress a retry — and the cause is a deterministic defect in the rail's approxCents derivation, so a retry re-mints a fresh credential and fails identically. Report it instead. |
+| `BCK.ROUTER.0010` | 500 | internal | ❌ | Router could not determine the amount to charge against the delegation cap | The payment handler reported a settlement amount in cents that is not a non-negative integer, so the routing-fee arithmetic cannot compute what to reserve. This is an internal invariant violation, not a bad request — the value is produced by Nevermined, not the caller. It deliberately fails rather than defaulting to zero, which would reserve nothing and let the payment through free. DO NOT BLIND-RETRY: no budget was reserved and no payment record was written, but a payment credential WAS already minted (on the card rail, a Stripe Shared Payment Token that will auto-expire). Because no record exists, your requestId will not suppress a retry — and the cause is a deterministic defect in the rail's approxCents derivation, so a retry re-mints a fresh credential and fails identically. Report it instead. |
| `BCK.ROUTER.0011` | 402 | business | ❌ | The card needs cardholder authentication (3-D Secure) before it can be used | This payment needs the cardholder to authenticate (3-D Secure / SCA) before the seller can charge it. The Router cannot complete that challenge — it needs a human at a browser, and an agent-initiated payment has none — so no usable credential was returned and NO money moved. Do NOT retry automatically: 3-D Secure is often mandated by industry rules for a given charge, in which case every retry demands it again, and each attempt creates a fresh single-use card credential that is then abandoned. It may succeed on a later attempt (whether authentication is demanded is decided per charge by the issuer, the card networks and Stripe's own risk checks), but treat that as a manual decision, not a loop. This is distinct from the delegation cap (BCK.ROUTER.0003) and from a card that was refused for lack of funds (BCK.ROUTER.0009): the card is fine, it simply has not been authenticated for this charge. The credential Stripe created is never handed to the seller and cannot be charged while it awaits authentication; it expires on its own, at the earliest of the merchant's quoted expiry, your delegation's expiry, or 89 days. |
+| `BCK.ROUTER.0012` | 400 | validation | ❌ | The 402 advertises an EIP-712 domain the settlement token does not sign under | Paying an x402 `exact` requirement means signing an EIP-3009 authorization under the settlement token's own EIP-712 domain, and the seller's 402 published an `extra.name`/`extra.version` that is not that token's. Nevermined signs under the domain it holds for the token, never one the counterparty supplies, so it refuses rather than produce an authorization whose published terms and signature disagree. NO money moved, no credential was issued, and no delegation budget was reserved — an authorization under the wrong domain is unspendable anyway, so nothing was lost by stopping. You only see this when EVERY option in the 402 failed the check: an option with a bad domain alongside a good one is skipped, not refused. This is the seller's bug (the values must match the token contract's `name()`/`version()` exactly, byte for byte — Base mainnet USDC is `"USD Coin"`, not `"USDC"`, and a JSON number `2` is not the string `"2"`), so report it to them and pay a different seller meanwhile; retrying will fail identically until they fix it. Distinct from BCK.ROUTER.0001, which means your request was malformed: here the request was fine and the counterparty's terms were not. Distinct from BCK.ROUTER.0013, which is the same check failing because NEVERMINED lacks the token's domain — that one is ours, not the seller's. |
+| `BCK.ROUTER.0013` | 500 | internal | ❌ | Nevermined holds no EIP-712 signing domain for the selected settlement token | An internal invariant broke: the funding filter selected a settlement token that Nevermined recognises as fundable, but for which it holds no EIP-712 domain (`name`/`version`) to sign the EIP-3009 authorization under. That is a gap in OUR canonical token table, not a problem with your request or with the seller — do not report it to the seller. It fails rather than falling back to the domain the seller advertised, because signing under a counterparty-supplied domain is exactly the trust this check exists to remove. NO money moved, no credential was issued and no delegation budget was reserved, so nothing needs unwinding. A retry fails identically until the table is fixed, so report it rather than looping; paying a seller that settles in a different token will work in the meantime. Distinct from BCK.ROUTER.0012, where the check failed because the SELLER advertised a domain its own token does not sign under. |
## `BCK.STRIPE`
@@ -600,6 +625,7 @@ Every error response from the Nevermined API carries a stable `code` (e.g. `BCK.
| `BCK.STRIPE.0022` | 424 | integration | — | The settlement could not be executed because the seller account has not properly configured the payment service provider (Stripe) | The plan seller has not completed Stripe Connect onboarding (charges_enabled is false). Ask the seller to finish onboarding before retrying the settlement. |
| `BCK.STRIPE.0023` | 503 | integration | — | Transient failure while looking up the seller payment service provider configuration | Inspect the underlying error in logs. The seller PSP-configuration lookup failed transiently — retry; if it persists, check DB connectivity. |
| `BCK.STRIPE.0024` | 424 | integration | ❌ | The organization owning the plan you are trying to purchase has not configured its payment service provider (Stripe). Contact the organization to complete the setup before retrying the purchase. | The plan is owned by an organization that has not connected Stripe (or has not completed Connect onboarding) for this environment. Surface the orgId / orgName carried in params so the buyer can identify the organization to contact. |
+| `BCK.STRIPE.0025` | 500 | internal | ❌ | The payment could not be routed to the seller and was not attempted | Internal defect, not a seller or buyer misconfiguration: a card charge reached the Stripe Connect split without a destination account and without an explicit platform-only opt-out, so it was refused before any PaymentIntent was created. Not reachable from any client input since #3136 removed the caller-settable merchantAccountId - if you are seeing this, a server-side caller failed to resolve a seller. No money moved. On the Visa rail a single-use VGS cryptogram and a Stripe PaymentMethod may already have been created for the attempt and are left unused - harmless, but it is not true that nothing external happened. Check the logged delegationId and how the caller resolved its merchant account. |
| `BCK.STRIPE.0030` | 500 | integration | — | Application-fee true-up refund failed; row left Settled with the owed amount stored in providerMetadata.trueUpRefundOwedMicro for manual reconciliation | The Stripe application-fee true-up refund failed. The settlement row is left as Settled with the owed amount in providerMetadata.trueUpRefundOwedMicro for manual reconciliation through Stripe Dashboard. |
| `BCK.STRIPE.0031` | 500 | internal | ❌ | Price conversion overflow when converting micro-units to cents | The plan price exceeds Number.MAX_SAFE_INTEGER after conversion. Lower the plan price or fix the unit boundary in convertMicroUnitsToCents. |
| `BCK.STRIPE.0032` | 500 | integration | ❌ | Stripe checkout: user profile not found for account event | The Stripe account event referenced a user that no longer exists in our DB (deleted profile, or environment mismatch between live/sandbox). The webhook is marked permanent so Stripe stops retrying. |
@@ -610,6 +636,7 @@ Every error response from the Nevermined API carries a stable `code` (e.g. `BCK.
| `BCK.STRIPE.0037` | 400 | integration | ✅ | Stripe subscription creation: no latest invoice on subscription | The newly-created subscription did not return a latest_invoice. Retry once; if it persists, check Stripe dashboard for the subscription state. |
| `BCK.STRIPE.0038` | 400 | integration | ✅ | Stripe subscription creation: no payment intent on subscription | The subscription invoice did not yield a payment_intent. This usually means the customer has no default payment method. Confirm the SetupIntent has succeeded before creating the subscription. |
| `BCK.STRIPE.0039` | 400 | business | ❌ | No Stripe account connected | The authenticated user has no personal Stripe account and belongs to no organization with one connected. Connect a Stripe account (Profile or Organization → Details) before requesting the account balance. |
+| `BCK.STRIPE.0040` | 424 | integration | ❌ | The seller Stripe Connect account is no longer reachable | The plan seller's Stripe Connect account was deauthorized, deleted, or its OAuth grant lapsed, so the platform can no longer pay out to it (Stripe: account_invalid). The stale validated flag has been cleared automatically; the seller must reconnect Stripe (Profile or Organization → Details). Not retryable until they do. |
## `BCK.STRIPE.CONNECT`
@@ -650,6 +677,9 @@ Every error response from the Nevermined API carries a stable `code` (e.g. `BCK.
| `BCK.TXS.0011` | 500 | integration | — | Error getting revenue time-series for owner | Transient server-side error building the revenue time-series; safe to retry. Inputs are validated upstream (invalid dates return 400, granularity is normalized), so this is not a bad-request issue. |
| `BCK.TXS.0012` | 500 | integration | — | Error getting requests time-series for owner | Transient server-side error building the requests time-series; safe to retry. Inputs are validated upstream (invalid dates return 400, granularity is normalized), so this is not a bad-request issue. |
| `BCK.TXS.0013` | 400 | business | — | startDate/endDate must be valid ISO-8601 timestamps | Pass startDate/endDate as ISO-8601 strings, e.g. 2024-01-01T00:00:00.000Z. |
+| `BCK.TXS.0014` | 500 | internal | ❌ | Owner-scoped read refused: the owner set is empty | Not caller-fixable and not retryable. The server derived an empty owner set for a tenant-scoped read and refused it rather than returning unscoped results; the correlation id in this response identifies the request in the logs. |
+| `BCK.TXS.0015` | 500 | integration | ✅ | Error getting the last plan created by owner | Usually a transient DB-layer fault on the last-created-plan lookup; retrying once is safe. If it persists, the owner address reaching the query is malformed, which a retry will not fix — quote the correlation id in this response. |
+| `BCK.TXS.0016` | 500 | internal | ❌ | Transaction search refused: the query has no scoping predicate | Not caller-fixable and not retryable. The server built a transaction search with no owner, consumer, plan or transaction id to scope it, and refused it rather than reading across every tenant; the correlation id in this response identifies the request in the logs. |
## `BCK.USER_PROFILE`
@@ -788,11 +818,14 @@ Every error response from the Nevermined API carries a stable `code` (e.g. `BCK.
| `BCK.X402.0047` | 500 | internal | ❌ | No card payment provider registered for the requested rail | Epic #1958 T1.C: CardPaymentProviderFactory.getProvider was asked for a card rail it has no provider instance for. CardProviderName aliases the growable CardSettlementProvider, so a newly-added PSP must be wired into the factory switch in the same change — an unhandled rail is a server-side wiring regression, never a client input error. Report the correlationId for investigation. |
| `BCK.X402.0048` | 502 | integration | ❌ | Network-token charge failed ambiguously (may have charged) — not retried or rolled back | Epic #1958 T2.D: a network-token charge through the PSP failed with an AMBIGUOUS error (timeout / 5xx / network / idempotency-key reuse) — the charge may actually have gone through. To avoid a double charge the spending reservation is deliberately LEFT IN PLACE (no rollback) and no other route is attempted. Reconcile the delegation against the PSP before any manual retry; the providerTransactionId in delegation_transactions is the breadcrumb. |
| `BCK.X402.0049` | 402 | business | ❌ | Network-token charge was declined by the payment provider | Epic #1958 T2.D: the PSP definitively declined the network-token charge (e.g. card_declined / insufficient_funds). No charge was captured, so the spending reservation is rolled back. Check the funding card or use a different payment method. |
-| `BCK.X402.0050` | 400 | validation | ❌ | Delegation currency has no settlement token on the plan network | An on-chain (erc4337) delegation must approve a real ERC-20 for its currency on the plan’s settlement network. The requested currency has no token configured on that network (e.g. EURC on Tempo, which settles only pathUSD/USDC) — minting the session key would produce a no-op approve that can never charge, so it is rejected. Pick a currency supported on the plan’s network (#1929). |
+| `BCK.X402.0050` | 400 | validation | ❌ | Delegation currency has no settlement token on the plan network | An on-chain (erc4337) delegation must approve a real ERC-20 for its currency on the plan’s settlement network. The requested currency has no token configured on that network — minting the session key would produce a no-op approve that can never charge, so it is rejected. Every served network carries both USDC and EURC today (Tempo gained EURC with the bridged EURC.e, #2631), so in practice this fires on a network added without a settlement token. Pick a currency supported on the plan’s network (#1929). |
| `BCK.X402.0051` | 503 | integration | ✅ | Chain RPC dependency temporarily unavailable during x402 verification | A transient failure of the on-chain RPC provider / bundler (5xx or unreachable) prevented an x402 verify/settle permission check from completing. Retry after a short backoff. If it persists, the RPC endpoint or its credentials may be misconfigured. The real upstream cause is captured server-side in the logs for this error id. |
-| `BCK.X402.0052` | 503 | integration | ✅ | EIP-7702 delegation could not be installed on the plan network | Installing the account’s Kernel v3.3 delegation designator on the plan’s network failed (bundler/paymaster/RPC), or a recent attempt is in its fail-closed backoff window. This is a transient infrastructure fault, not a client error — retry the request. See #2300. |
-| `BCK.X402.0053` | 404 | business | ❌ | Privy wallet no longer exists | The account’s embedded Privy wallet has been deleted, so its smart account can no longer be reconstructed. Privy states this is unrecoverable — neither Nevermined nor Privy can re-link an authentication method on the user’s behalf. The user profile survives but is no longer spendable; provision a new account. Distinct from BCK.X402.0011 ("user profile not found"), which means the profile itself is missing. See #2316. |
+| `BCK.X402.0052` | 503 | integration | ✅ | EIP-7702 delegation could not be installed on the plan network | Installing the account’s Kernel v3.3 delegation designator on the plan’s network failed (bundler/paymaster/RPC), or a recent attempt is in its fail-closed backoff window. This is a transient infrastructure fault, not a client error — retry the request. |
+| `BCK.X402.0053` | 404 | business | ❌ | Privy wallet no longer exists | The account’s embedded Privy wallet has been deleted, so its smart account can no longer be reconstructed. Privy states this is unrecoverable — neither Nevermined nor Privy can re-link an authentication method on the user’s behalf. The user profile survives but is no longer spendable; provision a new account. Distinct from BCK.X402.0011 ("user profile not found"), which means the profile itself is missing. |
| `BCK.X402.0054` | 402 | business | ❌ | account_access credential may only spend via the card-delegation scheme | This access token was minted for account-wide card spending, so it can only pay through the card-delegation scheme against its own pinned card delegation — not the crypto (nvm:erc4337) scheme, nor an inline-created or foreign delegation. Retry with the card-delegation scheme. #2568 §6.3. |
| `BCK.X402.0055` | 500 | internal | ❌ | Internal error: account_access binding has no delegation to spend against | A server-side data-integrity condition — an account_access binding always carries a card delegation (funding is required at authorize time). A null here should be unreachable; inspect the API logs. #2578. |
| `BCK.X402.0056` | 500 | internal | ❌ | EIP-7702 authorization was signed by a different account than the requested authority | The account recovered from the EIP-7702 authorization signature is not the authority whose on-chain nonce it was signed against, so the delegation would be rejected by the bundler or silently ignored on-chain. The usual cause is a stale stored EOA — the user profile’s `privyWalletAddress`, or an org wallet’s `address` column — pointing at a different account than the Privy wallet id actually resolves to. Retrying does not help until the stored address is repaired. The API logs for this error id name both the requested authority and the recovered signer. See #2740. |
+| `BCK.X402.0057` | 403 | business | ❌ | This credential does not own the referenced payment method or delegation | A card delegation must be created and spent by the SAME identity that enrolled the card. The credential you presented is not the owner of this payment method / delegation, so it can neither create nor spend it. Enroll the card, create the delegation, and spend under one identity. This is NOT a card decline, and NOT an allow-list problem — allow-listing a key cannot grant ownership (see BCK.X402.0029 for the allow-list / key-pin case). |
+| `BCK.X402.0058` | 502 | integration | ❌ | Payment could not be processed: the seller payment account is unavailable or the request was rejected | The payment processor rejected the request before any charge was attempted — most commonly the seller's Stripe Connect destination is missing or unreachable (`No such destination`), but also a lost BYOT entitlement or a malformed request. No charge was captured (rollback-safe), so this is NOT a card decline and retrying the same card will not help. Inspect params.stripeCode / params.stripeParam and the logged cause; a stale seller Connect account is self-healed (#2995) and the seller must reconnect Stripe. |
+| `BCK.X402.0059` | 402 | business | ❌ | Access token has already been used | This is a single-use (v3) access token and it was already settled. Mint a new token for each paid request — `POST /api/v1/x402/permissions` with `tokenVersion: 3` returns a fresh one. Reusable (v2) tokens are unaffected. This is NOT a signature or tampering failure (BCK.X402.0005) and NOT a payment decline. |