---
title: "Errors"
description: "Every error the Fluveo API returns: its code, HTTP status, message and what to do."
url: https://docs.fluveo.com/errors/
---

> Index of every page: https://docs.fluveo.com/llms.txt. Integrating Fluveo? Read https://docs.fluveo.com/agents/integrate.md first.

> Too long? This page with code in one language only: https://docs.fluveo.com/errors.curl.md (cURL), https://docs.fluveo.com/errors.node.md (Node.js), https://docs.fluveo.com/errors.python.md (Python), https://docs.fluveo.com/errors.php.md (PHP).

# Errors

Every error the Fluveo API returns: its code, HTTP status, message and what to do.

Every refusal has an HTTP status and a JSON body with one key, `error`. Branch on `error.code` when there is one, else on `error.type` and the HTTP status. `message` is for people and may change. Each error's `doc_url` points to its code on this page.

*An error body*

```json
{
  "error": {
    "type": "invalid_request_error",
    "code": "parameter_unknown",
    "param": "transfer_data",
    "message": "Received unknown parameter: transfer_data",
    "doc_url": "https://docs.fluveo.com/errors#parameter_unknown"
  }
}
```

| Field | What it is |
| --- | --- |
| `type` | The family of the error; the next table says when each one comes. |
| `code` | The precise reason, when there is one; the sections below. |
| `message` | A sentence for people. In a message, a part in square brackets appears only when its value is known. |
| `param` | The request parameter at fault, when there is one. |
| `decline_code` | On `card_declined`, the bank's reason. |
| `doc_url` | A link to the code on this page. |

| type | When you get it |
| --- | --- |
| `invalid_request_error` | Fluveo could not take the request as sent: a parameter is missing, unknown or wrong, the key is wrong, or the object does not exist. |
| `card_error` | The card was refused. `decline_code` gives the bank's reason when there is one. |
| `idempotency_error` | An `Idempotency-Key` came back with a request other than its first one. |
| `authentication_error` | A key that only the Dashboard may use was sent to the API. |
| `rate_limit_error` | Too many requests in a short time. Wait as long as `Retry-After` says. |
| `api_error` | Something failed on Fluveo's side. Retry with the same `Idempotency-Key`. |

A 4xx asks you to change the request. A 5xx, a 409 `idempotency_key_in_use` and a 429 `rate_limit` or `lock_timeout` may be retried with the same `Idempotency-Key`.

> **For AI agents:**
>
> Retry only 5xx, 409 and 429 answers, with the same Idempotency-Key and a growing wait; fix the request on any other 4xx. Never parse error.message.

## `account_invalid`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `This account cannot accept this request right now.` |
| 403 | `api_error` | `The provided key[ '{api_key}'] does not have access to account[ '{account}'] (or that account does not exist). Application access may have been revoked.` |
| 403 | `api_error` | `The provided key[ '{api_key}'] does not have access to account[ '{account}'] (or that account does not exist). Application access may have been revoked.` |

**What to do:** The store cannot take this request now; check its setup in the dashboard.

**What to do:** Use the key of the store that owns this object.

**What to do:** Use the key of the store that owns this object: each store calls Fluveo with its own key.

## `amount_too_large`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `The payment could not be captured because the requested capture amount is greater than the amount you can capture for this charge. Contact us via https://docs.fluveo.com/support/ for help.` |
| 400 | `invalid_request_error` | `The amount is greater than the maximum allowed for one payout on this account.` |

**What to do:** Capture at most amount_capturable of the PaymentIntent.

**What to do:** Send a smaller amount: this store has a limit for one payout.

## `amount_too_small`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `{message}` |
| 400 | `invalid_request_error` | `The Checkout Session's total amount must be at least {min} {currency} in minor units.` |

**What to do:** Raise the amount to at least the minimum the message names.

**What to do:** Raise the session's total: a usd session must come to at least 50 (0.50 USD).

## `api_key_expired`

| HTTP | type | message |
| --- | --- | --- |
| 401 | `invalid_request_error` | `Expired API Key provided: {api_key}` |

**What to do:** The key was rolled or revoked and no longer works: send the store's current secret key, sk_test_..., from the dashboard's API keys.

## `approval_invalid`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `No such approval request for this key. Send the request again without the Fluveo-Approval header to get a new one.` |

**What to do:** The approval in Fluveo-Approval cannot be used for this request: it is unknown, not approved yet, denied, expired, made for other parameters, or used too long ago. Read the message; when it names an earlier approval, retry with that one, else send the request again without the header to get a new approval.

## `approval_required`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `This request needs a person's approval before it runs, and nothing ran. Ask a person to approve {approval_request} at {approval_url}, then retry the same request with the same parameters, the same Idempotency-Key if it sent one, and the header 'Fluveo-Approval: {approval_request}'.` |

**What to do:** Nothing ran: a person must approve this request first. Show the approval_url to a person who can approve it in the Dashboard; once approved, retry the same request with the same parameters, the same Idempotency-Key and the header Fluveo-Approval: <approval_request>. A POST that needs approval must send an Idempotency-Key.

## `authentication_failure`

| HTTP | type | message |
| --- | --- | --- |
| 402 | `card_error` | It varies with the case; read it from the answer. |

The card's bank could not confirm the customer in its 3D Secure check, so the payment did not go through.

**What to do:** Ask the customer to try again and finish the bank's check, or to pay with another card.

## `authentication_required`

| HTTP | type | message |
| --- | --- | --- |
| 402 | `card_error` | It varies with the case; read it from the answer. |

The bank declined because this payment needs the customer to authenticate with 3D Secure, and the attempt did not include it.

**What to do:** Confirm again with the customer present so they can finish the bank's check; for an off-session payment, bring the customer back to pay.

## `automatic_tax_unavailable`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `Automatic tax is not available yet: Fluveo has no tax engine.` |

The payment link asked for automatic_tax[enabled]=true, and Fluveo computes no tax.

**What to do:** Send automatic_tax[enabled]=false or leave automatic_tax out.

## `balance_insufficient`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `Fluveo can't complete this operation because the associated account doesn't have enough available balance.` |
| 400 | `invalid_request_error` | `You have insufficient funds in your Fluveo account for this transfer. Your card balance is too low.  You can use the /v1/balance endpoint to view your Fluveo balance (for more details, see https://docs.fluveo.com/api#balance).` |

**What to do:** Wait until the balance covers the refund, then create it again with a new Idempotency-Key: the same key returns this same answer.

**What to do:** Lower the payout amount to what the available balance allows.

## `card_decline_rate_limit_exceeded`

| HTTP | type | message |
| --- | --- | --- |
| 402 | `card_error` | It varies with the case; read it from the answer. |

This card was declined too many times in a short time, so new attempts with it are refused for now.

**What to do:** Wait about a day before you try this card again, or ask the customer for another card.

## `card_declined`

| HTTP | type | message |
| --- | --- | --- |
| 402 | `card_error` | `Your card was declined.` |
| 402 | `card_error` | `Your card was declined.` |

**What to do:** The payment was declined as risky. Ask the buyer for another payment method; do not retry the same card.

**What to do:** Ask the buyer for another card or payment method. decline_code tells the bank's reason.

## `charge_already_captured`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `Charge {charge} has already been captured.` |

**What to do:** Nothing to do: the charge is already captured.

## `charge_already_refunded`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `Charge[ {charge}] has already been refunded.` |

**What to do:** Nothing to do: the charge is already fully refunded.

## `charge_disputed`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `Charge {charge} has been charged back; cannot issue a refund.` |

The charge has a chargeback, so it cannot be refunded.

**What to do:** Do not refund it: the dispute decides where the money goes. Answer the dispute instead.

## `charge_expired_for_capture`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `The charge can't be captured because its authorization is no longer available. Cancel this PaymentIntent, then create a new one to charge the customer again.` |

The authorization behind this PaymentIntent is no longer available, so it can never be captured. Nothing was captured or charged.

**What to do:** Cancel the PaymentIntent (it answers canceled and releases nothing, since no authorization is left), then create a new PaymentIntent to charge the customer again. A refund of such a payment ends failed with failure_reason unknown and gives its amount back.

## `content_type_invalid`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `A multipart boundary is required.` |

A file upload came without a multipart/form-data Content-Type that names a boundary.

**What to do:** Send the upload as multipart/form-data; most HTTP clients add the boundary for you when you build a multipart body.

## `country_code_invalid`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `'{country}' is not a valid country for a Brazilian address ('BR' required).` |

**What to do:** Send country BR for a Brazilian address.

## `custom_fields_invalid_numeric`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `You can only specify numeric characters for `custom_fields[][numeric][value]`.` |

A numeric custom field's default value holds a character that is not a digit.

**What to do:** Send only digits in custom_fields[][numeric][default_value].

## `email_invalid`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `Invalid email address: {email}` |

**What to do:** Send a valid email address.

## `expired_card`

| HTTP | type | message |
| --- | --- | --- |
| 402 | `card_error` | It varies with the case; read it from the answer. |

The card is past its expiry date.

**What to do:** Ask the customer for a card that is still valid, or for the new expiry date of a reissued card.

## `files_unavailable`

| HTTP | type | message |
| --- | --- | --- |
| 503 | `api_error` | `The files service is unavailable.` |

The service that stores files could not be reached, so nothing was read or stored.

**What to do:** Retry later with the same Idempotency-Key; if it keeps failing, contact Fluveo support with the request id.

## `header_invalid`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `Duplicate request header.` |

A files request sent the same header twice, or a header value that is not plain text.

**What to do:** Send Content-Type and Idempotency-Key at most once each, with ASCII values.

## `idempotency_key_in_use`

| HTTP | type | message |
| --- | --- | --- |
| 409 | `invalid_request_error` | `There is currently another in-progress request using this Idempotent Key (that probably means you submitted twice, and the other request is still going through)[: {idempotency_key}]. Please try again later.` |

**What to do:** Wait for the first request with this Idempotency-Key to finish, then retry with the same key.

## `incorrect_address`

| HTTP | type | message |
| --- | --- | --- |
| 402 | `card_error` | It varies with the case; read it from the answer. |

The address does not match the one the bank has for the card.

**What to do:** Ask the customer to check the card's address, or to pay with another card.

## `incorrect_cvc`

| HTTP | type | message |
| --- | --- | --- |
| 402 | `card_error` | It varies with the case; read it from the answer. |

The security code does not match the card.

**What to do:** Ask the customer to enter the card's security code again.

## `incorrect_number`

| HTTP | type | message |
| --- | --- | --- |
| 402 | `card_error` | `Your card number is incorrect.` |

**What to do:** Ask the buyer to check the card number.

## `incorrect_zip`

| HTTP | type | message |
| --- | --- | --- |
| 402 | `card_error` | It varies with the case; read it from the answer. |

The postal code does not match the address the bank has for the card.

**What to do:** Ask the customer to check the postal code of the card's address.

## `instant_payouts_unsupported`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `Instant Payouts are not enabled for this account.` |

**What to do:** Send method=standard, or leave method out.

## `invalid_cvc`

| HTTP | type | message |
| --- | --- | --- |
| 402 | `card_error` | `Your card's security code is invalid.` |

**What to do:** Ask the buyer to check the security code.

## `invalid_expiry_month`

| HTTP | type | message |
| --- | --- | --- |
| 402 | `card_error` | `Your card's expiration month is invalid.` |

**What to do:** Ask the buyer to check the expiry month.

## `invalid_expiry_year`

| HTTP | type | message |
| --- | --- | --- |
| 402 | `card_error` | `Your card's expiration year is invalid.` |

**What to do:** Ask the buyer to check the expiry year.

## `invalid_mandate_reference_prefix_format`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `{message}` |

**What to do:** Send a prefix of at most 12 uppercase letters, digits, spaces or the characters the message lists.

## `invalid_number`

| HTTP | type | message |
| --- | --- | --- |
| 402 | `card_error` | `The card number is not a valid credit card number.` |

**What to do:** Ask the buyer to check the card number.

## `lock_timeout`

| HTTP | type | message |
| --- | --- | --- |
| 429 | `invalid_request_error` | `This object cannot be accessed right now because another API request or Fluveo process is currently accessing it. If you see this error intermittently, retry the request. If you see this error frequently and are making multiple concurrent requests to a single object, make your requests serially or at a lower rate.` |

**What to do:** Another request is changing the same object; retry shortly with the same Idempotency-Key.

## `managed_payments_unavailable`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `Managed Payments is not available on Fluveo.` |

The payment link asked for managed_payments[enabled]=true, which Fluveo does not offer.

**What to do:** Send managed_payments[enabled]=false or leave managed_payments out.

## `missing`

| HTTP | type | message |
| --- | --- | --- |
| 402 | `card_error` | `This Customer doesn't have any saved payment details. Attach a legacy Token, Card, Bank Account, or Source to this Customer and then try this request again, or use Payment Intents and Payment Methods instead.` |

**What to do:** Create a PaymentIntent with the customer and one of its PaymentMethods instead: a Fluveo customer holds no legacy source.

## `multipart_invalid`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `The multipart request is invalid.` |

The files service could not read the multipart body of the upload.

**What to do:** Check that the body is well-formed multipart/form-data with a file part and a purpose field, then send it again.

## `not_available`

| HTTP | type | message |
| --- | --- | --- |
| 403 | `invalid_request_error` | `This API is not available on this account. If its setup is not finished or is still under review, finish it in the Dashboard under Settings and try again once the account is approved.` |

**What to do:** This store cannot use this route or mode yet. If its setup is not finished, finish it in the Dashboard under Settings; if it is under review, try again once the account is approved; if the route is not enabled for the store, use only the routes this reference lists.

## `not_found`

| HTTP | type | message |
| --- | --- | --- |
| 404 | `invalid_request_error` | `Unrecognized request URL. This endpoint is available at {files_host} instead of {api_host}. Please try using {files_url} or see {docs} for more information.` |

The URL is served on another host: a file's contents are downloaded from the files host, not from the API host.

**What to do:** Download the contents from the file's url, which names the files host, with the same API key.

## `parameter_invalid_boolean`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `{message}` |

A payment link field that takes true or false got another value, or a value the link cannot take, such as custom_unit_amount[enabled]=false, or active=true on an expired link, which cannot be reactivated; param names it.

**What to do:** Send the value the message names in the field named in param, or leave the field out; to sell again after the link expired, create a new payment link.

## `parameter_invalid_combination`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `{message}` |

Two parameters that cannot go together were both sent, such as starting_after with ending_before on the payment links list.

**What to do:** Send only one of the two parameters the message names.

## `parameter_invalid_empty`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `You passed an empty string for '{param}'. We assume empty values are an attempt to unset a parameter; however '{param}' cannot be unset. You should remove '{param}' from your request or supply a non-empty value.` |
| 400 | `invalid_request_error` | `You passed an empty string for '{param}'. We assume empty values are an attempt to unset a parameter; however '{param}' cannot be unset. You should remove '{param}' from your request or supply a non-empty value.` |

**What to do:** Send a value in the field named in param, or leave the field out.

## `parameter_invalid_enum`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `{message}` |

A payment link field got a value outside the list it takes; param names it, and the message the value received.

**What to do:** Send one of the values the reference lists for the field named in param.

## `parameter_invalid_integer`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `Invalid integer.` |
| 400 | `invalid_request_error` | `This value must be greater than or equal to 1.` |
| 400 | `invalid_request_error` | `This value must be less than or equal to 9999999999 (it currently is '{amount}').` |
| 400 | `invalid_request_error` | `This value must be greater than or equal to {minimum}.` |
| 400 | `invalid_request_error` | `{message}` |

**What to do:** Send a whole number in the field named in param, with no decimals or spaces.

**What to do:** Send an amount of at least 1, in the smallest unit of the currency.

**What to do:** Send an amount of at most 9999999999, in the smallest unit of the currency.

**What to do:** Send a value at least as large as the minimum the message names, in the field named in param.

**What to do:** Send a whole number within the range the message gives, in the field named in param.

## `parameter_invalid_object`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `{message}` |

A payment link field that takes an object or a list, such as metadata, line_items, custom_unit_amount or after_completion, got another shape, too many entries, or a mix the link cannot take, such as amount with line_items; param names it.

**What to do:** Send the field named in param as the reference describes it, within the limits and the one pricing choice the message gives.

## `parameter_invalid_string`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `{message}` |

A payment link field got a text it cannot take, such as a value that is too long, a value that is not an id of the right kind, a currency that is not a three-letter code, or a currency change on an existing link; param names it.

**What to do:** Fix the value of the field named in param as the message says; to sell in another currency, create a new payment link.

## `parameter_missing`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `Missing required param: {param}.` |
| 400 | `invalid_request_error` | `The `payment_method`parameter supplied {id} belongs to the Customer {owner}. Please include the Customer in the`customer` parameter on the PaymentIntent.` |

**What to do:** Add the required field named in param.

**What to do:** Send the PaymentMethod's Customer in customer, or use a PaymentMethod that belongs to no Customer.

## `parameter_unknown`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `Received unknown parameter: {param}[. Did you mean {suggestion}?]` |

**What to do:** Remove the parameter named in param. Send only the parameters the reference lists for this operation.

## `payment_intent_invalid_parameter`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `The payment method type "{type}" is invalid. Please ensure the provided type is activated in your dashboard and your account is enabled for any preview features that you are trying to use.` |
| 400 | `invalid_request_error` | `{message}` |

**What to do:** Use card, or pix or boleto when the store takes them.

**What to do:** Send the field named in param in the form the message gives.

## `payment_intent_unexpected_state`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `This PaymentIntent cannot perform this action[ because it has a status of {status}].` |

**What to do:** Read the PaymentIntent and act on its current status; this action is not allowed in that status.

## `payment_link_inactive`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `Expired payment links cannot be edited. Create a new payment link.` |

The payment link expired, so it can no longer be changed. A link that reached its payment limit, or that you switched off, still takes changes.

**What to do:** Create a new payment link with the changes you wanted.

## `payment_link_no_valid_payment_methods`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `No valid payment method types for this payment link. Its amount is above the most one payment can charge: 99999999 in the currency's smallest unit, such as 999,999.99 USD or BRL.` |

The payment link's total is above what one payment can charge, so no payment method could take it.

**What to do:** Lower the link's amount or quantity so one payment comes to at most 99999999 in the currency's smallest unit.

## `payment_method_not_available`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `Boleto is not available for this payment.` |
| 400 | `invalid_request_error` | `This payment method is not available for this payment.` |

**What to do:** Offer another payment method: Boleto is not available for this payment.

**What to do:** Use a payment method the store accepts: card, or pix or boleto when the store takes them.

## `payment_method_restricted`

| HTTP | type | message |
| --- | --- | --- |
| 402 | `card_error` | It varies with the case; read it from the answer. |

The bank or the card network does not allow this card for this payment, for example for this kind of store or country.

**What to do:** Ask the customer for another payment method.

## `payment_method_unexpected_state`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `The PaymentMethod on this PaymentIntent was previously used without being attached to a Customer or was detached from a Customer, and may not be used again. You can try confirming again with a new PaymentMethod.` |

**What to do:** Confirm again with a new PaymentMethod: this one belongs to a deleted Customer.

## `payment_method_unsupported_type`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `This payment method of card type does not support attaching to self.` |

A SetupIntent with attach_to_self=true was confirmed; a card cannot be attached to the account itself.

**What to do:** Create or update the SetupIntent without attach_to_self=true, or with attach_to_self=false, and confirm it again.

## `payouts_not_allowed`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `Payouts have been disabled on this account[: {reason}].` |

**What to do:** Payouts are turned off for this store; check its setup in the dashboard.

## `plink_no_longer_accepts_payments`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `This link can no longer accept payments. Contact the seller for more information.` |

The buyer pressed Pay on a checkout opened from a payment link that has since reached its payment limit, been switched off or expired. The API refuses the payment, and no money moves.

**What to do:** For a link at its limit, raise restrictions[completed_sessions][limit] above its count with active=true; for a link you switched off, send active=true; for an expired link, share a new payment link. The buyer then opens the link again.

## `postal_code_invalid`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `Invalid postal code for Brazil. Must be an eight-digit code registered by Correios.` |

**What to do:** Send an eight-digit CEP.

## `processing_error`

| HTTP | type | message |
| --- | --- | --- |
| 402 | `card_error` | It varies with the case; read it from the answer. |

Something failed while the card was being processed; the card itself may be fine.

**What to do:** Try the payment again a little later as a new request with a new Idempotency-Key; if it keeps failing, ask for another card.

## `property_expansion_max_depth`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `You cannot expand more than 4 levels of a property.[ Property: {path}]` |

**What to do:** Shorten the expand path, or fetch the nested object with its own request.

## `rate_limit`

| HTTP | type | message |
| --- | --- | --- |
| 429 | `rate_limit_error` | `Request rate limit exceeded.` |

**What to do:** Slow down: wait as long as the Retry-After header says, then retry.

## `rate_limit_unavailable`

| HTTP | type | message |
| --- | --- | --- |
| 503 | `api_error` | `Test events are temporarily unavailable; retry.` |

Fluveo could not read the limit on test webhook events, so it sent nothing. Dashboard only.

**What to do:** Retry in a moment; nothing was sent, so a retry cannot send twice.

## `refund_in_progress`

| HTTP | type | message |
| --- | --- | --- |
| 409 | `invalid_request_error` | `This payment already has a refund in progress[ ({refund})]. Wait until it succeeds or fails, then create the next refund.` |

**What to do:** Wait until the refund in progress succeeds or fails, then create the next one.

## `resource_already_exists`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `{what} already exists.` |

**What to do:** Choose another id, or leave id out so Fluveo draws one. An id is unique within your store and mode.

## `resource_missing`

| HTTP | type | message |
| --- | --- | --- |
| 404; 400 when param is `default_price`; 400 when param is `destination`; 400 when param is `ending_before`; 400 when param is `starting_after`; 400 when param is `token` | `invalid_request_error` | `No such {object}[: '{id}']` |

**What to do:** Check the id and that it belongs to the store of your key; ids from another store or mode are not found.

## `secret_key_required`

| HTTP | type | message |
| --- | --- | --- |
| 403 | `invalid_request_error` | `This API call cannot be made with a publishable API key. Please use a secret API key. You can find a list of your API keys at https://docs.fluveo.com/start/authentication#get-a-key-from-the-dashboard.` |

**What to do:** Send the store's secret key, sk_test_..., not its publishable key pk_test_...: every /v1 route takes the secret key.

## `setup_intent_authentication_failure`

| HTTP | type | message |
| --- | --- | --- |
| varies | `invalid_request_error` | `The latest attempt to set up the payment method has failed because authentication failed.` |

The buyer failed or left their bank's 3D Secure check, so the card was not saved. It comes as the SetupIntent's last_setup_error, and the SetupIntent goes back to requires_payment_method.

**What to do:** Ask the buyer to confirm again and finish the bank's check, or to save another card.

## `setup_intent_invalid_parameter`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `The parameter `return_url`cannot be passed when creating a SetupIntent unless`confirm` is set to true.` |

A SetupIntent parameter does not fit the request: return_url or mandate_data on a create without confirm=true, single_use on a card SetupIntent's confirm, or excluded_payment_method_types that leaves no type.

**What to do:** Send confirm=true with return_url or mandate_data on the create, create the SetupIntent without single_use, and keep card out of excluded_payment_method_types.

## `setup_intent_unexpected_state`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | It varies with the case; read it from the answer. |

The SetupIntent's status does not allow this call: a confirm with no payment method; an update or a confirm of a SetupIntent that already succeeded, was canceled, is processing or waits for the buyer's 3D Secure; or a cancel of one that already succeeded, was canceled or is processing. The answer carries the SetupIntent as it stands, except after a create with confirm=true and no payment method, which makes no SetupIntent.

**What to do:** Send a payment_method with the confirm. Otherwise read setup_intent.status in the answer and act on it: create a new SetupIntent for a succeeded or canceled one, or wait for one that is processing or for the buyer to finish next_action.

## `tax_id_invalid`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `Invalid value for {type}.` |

**What to do:** Send a valid CPF (11 digits) or CNPJ (14 digits).

## `tax_id_prohibited`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `A tax identifier may not be provided on this payment method as it is not required.` |

**What to do:** Remove the tax id: this payment method does not take one.

## `test_mode_only`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `Test events can be sent only in Test mode.` |

Test webhook events can be sent only in test mode. Dashboard only.

**What to do:** Switch the dashboard to test mode and try again.

## `three_d_secure_authentication_not_supported`

| HTTP | type | message |
| --- | --- | --- |
| 402 | `card_error` | It varies with the case; read it from the answer. |

The card does not support 3D Secure, and this payment needs it.

**What to do:** Ask the customer to pay with another card.

## `token_already_used`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `The token {id} has already been used. Each token can only be used once to create a source.` |

**What to do:** Create a new token from new Apple Pay payment data: each token makes one PaymentMethod.

## `unsupported_operation`

| HTTP | type | message |
| --- | --- | --- |
| 404 | `invalid_request_error` | `The resource or operation at `{path}` is not supported by this API.` |

The path is not an operation this API offers to you.

**What to do:** Check the method and path against this reference.

## `url_invalid`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `Not a valid URL` |
| 400 | `invalid_request_error` | `{message}` |

**What to do:** Send a full URL with its scheme, such as https://example.com/return.

**What to do:** Send a full URL with its scheme, such as https://, in the field named in param.

## `webhook_attempts_unavailable`

| HTTP | type | message |
| --- | --- | --- |
| 503 | `api_error` | `Delivery attempts are unavailable; retry.` |

Fluveo could not read the endpoint's delivery attempts. Dashboard only.

**What to do:** Retry in a moment; if it keeps failing, contact Fluveo support with the request id.

## `webhook_test_destination_changed`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `The endpoint's URL changed while this test event was being prepared. Nothing was sent; send it again.` |

The webhook endpoint's URL changed while the test event was being prepared, so Fluveo sent nothing. Dashboard only.

**What to do:** Send the test event again.

## `webhook_test_port_unsupported`

| HTTP | type | message |
| --- | --- | --- |
| 400 | `invalid_request_error` | `Test events can be sent only to a publicly accessible URL.` |

A test webhook event goes where a real test-mode delivery goes, http or https on any port, and this endpoint's URL names an internal host or a private address. Dashboard only.

**What to do:** Change the endpoint's URL to a publicly reachable address, or test against another endpoint.

## Errors without a code

These answer with a `type` and a message but no `code`.

| HTTP | type | message | What to do |
| --- | --- | --- | --- |
| 401 | `invalid_request_error` | `Invalid API Key provided: {api_key}` | Check the key: send the store's secret key, sk_test_..., as Authorization: Bearer <key>. |
| 401 | `invalid_request_error` | `You did not provide an API key. You need to provide your API key in the Authorization header, using Bearer auth (e.g. 'Authorization: Bearer YOUR_SECRET_KEY'). See https://docs.fluveo.com/start/authentication for details, or we can help at https://docs.fluveo.com/support/.` | Add the header Authorization: Bearer sk_test_... to every call. |
| 403 | `invalid_request_error` | `Live mode is not available yet: this API serves test mode only. Use your test secret key (sk_test_...).` | Fluveo serves no live mode yet, so a live key, sk_live_..., is refused even when it is right. Use the store's test secret key, sk_test_... |
| 403 | `invalid_request_error` | `The provided key '{key}' does not have the required permissions for this endpoint on account '{account}'. Having the 'rak_{resource}_{access}' permission would allow this request to continue.` | Give this restricted key the permission the message names in the Dashboard under Settings, API keys, or call with a key that has it. A route the message says is not available to restricted keys needs a secret key. |
| 404 | `invalid_request_error` | `Unrecognized request URL ({method}: {path}). Please see https://docs.fluveo.com or we can help at https://docs.fluveo.com/support/.` | Fix the method or the path: Fluveo does not serve it. Check the reference for the routes that exist. |
| 400 | `invalid_request_error` | `You cannot use this method on your own account: change your account in the Dashboard under Settings.` | Change your account in the Dashboard under Settings; the API reads it with GET /v1/account. |
| 400 | `invalid_request_error` | `Invalid value[ for {param}][: {reason}].` | Fix the value of the field named in param; the message says what is wrong. |
| 400 | `idempotency_error` | `Keys for idempotent requests can only be used with the same parameters they were first used with. Try using a key other than '{idempotency_key}' if you meant to execute a different request.` | Use a new Idempotency-Key for a new request. Reuse a key only to retry the exact same request. |
| 400 | `invalid_request_error` | `The Boleto PaymentIntent cannot be updated or canceled when it has a requires_action status. You must either wait for the payment instructions to expire or for your customer to complete the payment.` | Wait: an issued Boleto can still be paid, so it cannot be canceled. It ends paid, or failed once its overdue limit passes. |
| 400 | `invalid_request_error` | `The provided PaymentMethod was previously used with a PaymentIntent without Customer attachment, or was detached from a Customer. It may not be used again. To use a PaymentMethod multiple times, you must attach it to a Customer first.` | Use another PaymentMethod, or attach or detach this one first as the message says. |
| 400 | `invalid_request_error` | `Refund amount is greater than the amount left to refund on this charge.` | Lower the refund amount to what is left to refund on the charge. |
| 400 | `invalid_request_error` | `Refunds are not supported on this payment method.` | This payment method cannot be refunded through the API; settle it with the buyer another way. |
| 400 | `invalid_request_error` | `{message}` | Read the message: it names the field and the fix. |
| 400 | `invalid_request_error` | `Invalid request (check your POST parameters): unable to determine value for parameter[: {name}]. For assistance, contact support at https://docs.fluveo.com/support/.` | Send the named parameter in one form only: a value, a hash (name[key]) or a list (name[]), never two of them. |
| 400 | `invalid_request_error` | `This PaymentIntent is configured to accept payment methods enabled in your Dashboard. Because some of these payment methods might redirect your customer off of your page, you must provide a `return_url`. If you don't want to accept redirect-based payment methods, set `automatic_payment_methods[enabled]`to`true`and`automatic_payment_methods[allow_redirects]`to`never` when creating Setup Intents and Payment Intents.` | Send return_url on the confirm, or create the PaymentIntent or SetupIntent with automatic_payment_methods[allow_redirects]=never or with payment_method_types. A PaymentIntent confirmed with off_session=true needs neither. |
| 400 | `invalid_request_error` | `Your account cannot currently make charges. To find out why charge creation is currently disabled, look at the `requirements.disabled_reason` property on this account (/v1/accounts/{account}).` | The store is suspended and takes no new payment. Contact Fluveo support to have the store reviewed and reactivated, then confirm again. |
| 400 | `invalid_request_error` | `This account is not currently able to close disputes. Please contact us via https://docs.fluveo.com/support/ for further information.` | The store is suspended and cannot close a dispute. Contact Fluveo support to have the store reactivated, then close the dispute; you can still update its evidence meanwhile. |
| 500 | `api_error` | `An unknown error occurred` | An error on Fluveo's side. Retry with the same Idempotency-Key; if it keeps failing, contact support with the Request-Id header. |
| 500 | `api_error` | `Sorry, something went wrong. We've already been notified of the problem, but if you need any help, you can reach us at https://docs.fluveo.com/support/.` | A form key was nested past 31 bracket segments (metadata[a][a]...). Send keys at most 31 segments deep. |
| 503 | `api_error` | `An unknown error occurred` | Fluveo could not finish the payment in time. Retry later with the same Idempotency-Key. |
| 400 | `invalid_request_error` | `Invalid currency[: {currency}]. This account does not accept payments in this currency.` | Send the currency the store accepts. |
| 400 | `invalid_request_error` | ``capture_method=manual`is not supported by payment method type`{method}`. Use a different capture method.` | Leave capture_method out, or send automatic: a Pix or a Boleto is captured when it is paid. |
| 400 | `invalid_request_error` | `The PaymentMethod[ {id}] does not belong to the Customer you supplied[ {customer}]. Please use this PaymentMethod with the Customer that it belongs to instead.` | Use a PaymentMethod attached to the PaymentIntent's customer, or change the customer. |
| 400 | `invalid_request_error` | `Invalid Fluveo API version[: {version}]` | Send Fluveo-Version: 2026-05-27.dahlia, or leave the header out. |
| 400 | `invalid_request_error` | `This property cannot be expanded[ ({path})].[ You may want to try expanding '{suggestion}' instead.]` | Expand only the fields marked expandable, up to four levels deep. |
| 400 | `invalid_request_error` | `Received both payment_method and payment_method_data parameters. Please pass in only one.` | Send payment_method or payment_method_data, not both. |
| 400 | `invalid_request_error` | `Invalid {param}: must be one of {types}` | Use one of the types the message lists. |
| 503 | `api_error` | `Ledger data is temporarily unavailable.` | Fluveo's book of money did not answer. Retry shortly with the same Idempotency-Key. |
| 503 | `api_error` | `Balance temporarily unavailable; retry shortly.` | Retry shortly. |
| 400 | `invalid_request_error` | `Invalid BR state code.` | Send a two-letter Brazilian state code, such as SP. |
| 401 | `authentication_error` | `Invalid API Key provided.` | Use the store's secret key; this route is for the dashboard. |
| 402 | `invalid_request_error` | `Sending credit card numbers directly to the Fluveo API is generally unsafe. We suggest you use test tokens that map to the test card you are using, see https://docs.fluveo.com/start/testing. To enable testing raw card data APIs, see https://docs.fluveo.com/payments/cards#raw-card-numbers.` | Never send card numbers to the API. Use Checkout, or the pm_card_* test PaymentMethods in test mode. |
| 404 | `invalid_request_error` | `Invalid request` | Use a PaymentMethod attached to this customer. |
