Docs
API 2026-05-27.dahlia Dashboard

Get started

What test mode does, how each test card ends, and what a test Pix or Boleto does.

Everything a sk_test_ key does stays in test data: cards are not charged, banks see nothing, and every object carries livemode: false. Build and check your whole integration this way. Fluveo serves only test mode today. See Authentication.

In test mode Fluveo does not e-mail your store's notices to your address, such as a payment, a dispute, a request for more details to verify your business or the news that it is verified: the Dashboard shows each of them, and Activation in Settings shows your verification.

Pay with a test card#

You never send card numbers to the API. In test mode, pass one of the names below as payment_method when you create and confirm a PaymentIntent, or when you confirm it later. Each use makes a new PaymentMethod (pm_...) in your store with the brand and last four digits shown.

Pay with a test card
curl https://api.fluveo.com/v1/payment_intents \
  -H "Authorization: Bearer sk_test_..." \
  -H "Idempotency-Key: test-decline-1" \
  -d amount=2000 \
  -d currency=usd \
  -d "payment_method_types[]=card" \
  -d payment_method=pm_card_visa_chargeDeclined \
  -d confirm=true
const response = await fetch("https://api.fluveo.com/v1/payment_intents", {
  method: "POST",
  headers: { Authorization: "Bearer sk_test_...", "Idempotency-Key": "test-decline-1" },
  body: new URLSearchParams({
    amount: "2000",
    currency: "usd",
    "payment_method_types[]": "card",
    payment_method: "pm_card_visa_chargeDeclined",
    confirm: "true",
  }),
});
const body = await response.json();
console.log(response.status, body.error?.code, body.error?.decline_code);
import requests

response = requests.post(
    "https://api.fluveo.com/v1/payment_intents",
    headers={"Authorization": "Bearer sk_test_...", "Idempotency-Key": "test-decline-1"},
    data={
        "amount": 2000,
        "currency": "usd",
        "payment_method_types[]": "card",
        "payment_method": "pm_card_visa_chargeDeclined",
        "confirm": "true",
    },
)
error = response.json().get("error", {})
print(response.status_code, error.get("code"), error.get("decline_code"))
<?php
$ch = curl_init("https://api.fluveo.com/v1/payment_intents");
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => ["Authorization: Bearer sk_test_...", "Idempotency-Key: test-decline-1"],
    CURLOPT_POSTFIELDS => http_build_query([
        "amount" => 2000,
        "currency" => "usd",
        "payment_method_types" => ["card"],
        "payment_method" => "pm_card_visa_chargeDeclined",
        "confirm" => "true",
    ]),
]);
$body = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_HTTP_CODE) . " " . ($body["error"]["code"] ?? "") . " " . ($body["error"]["decline_code"] ?? "");

Successful payments#

payment_methodBrandLast 4Outcome
pm_card_visaVisa, credit4242The payment succeeds.
pm_card_visa_debitVisa, debit5556The payment succeeds.
pm_card_mastercardMastercard, credit4444The payment succeeds.
pm_card_amexAmerican Express, credit0005The payment succeeds.

Declines#

A decline answers 402 with error.type card_error. The PaymentIntent stays in requires_payment_method, so you can confirm it again with another payment method.

payment_methodLast 4error.codeerror.decline_code
pm_card_visa_chargeDeclined0002card_declinedgeneric_decline
pm_card_visa_chargeDeclinedInsufficientFunds9995card_declinedinsufficient_funds
pm_card_chargeDeclinedExpiredCard0069expired_cardnone
pm_card_chargeDeclinedIncorrectCvc0127incorrect_cvcnone
pm_card_chargeDeclinedProcessingError0119processing_errornone

3D Secure#

These cards ask the buyer to authenticate. Confirm them with a return_url: the answer is 200 with status requires_action and a next_action of type redirect_to_url. In test mode, next_action.redirect_to_url.url opens a test page with two buttons, Complete and Fail, and then sends the buyer to your return_url with payment_intent, payment_intent_client_secret and redirect_status (succeeded or failed) in the query. Confirmed without a return_url, a PaymentIntent created with payment_method_types answers requires_action with a next_action of type use_fluveo_sdk that cannot be completed, and one created without payment_method_types is refused with 400 and nothing is charged; confirmed with error_on_requires_action=true, each one answers 402 card_error with error.code authentication_required.

payment_methodLast 4After CompleteAfter Fail
pm_card_threeDSecure2Required3220succeededrequires_payment_method, last_payment_error.code payment_intent_authentication_failure
pm_card_authenticationRequired3184succeededrequires_payment_method, last_payment_error.code payment_intent_authentication_failure
pm_card_authenticationRequiredChargeDeclinedInsufficientFunds3178requires_payment_method, card_declined with insufficient_fundsrequires_payment_method, last_payment_error.code payment_intent_authentication_failure
pm_card_threeDSecureRequiredChargeDeclined1629requires_payment_method, card_declined with generic_declinerequires_payment_method, last_payment_error.code payment_intent_authentication_failure
pm_card_threeDSecureRequiredProcessingError1280requires_payment_method, processing_errorrequires_payment_method, last_payment_error.code payment_intent_authentication_failure

Refunds and disputes#

payment_methodLast 4Outcome
pm_card_refundFail5126The payment succeeds. A refund of it is created, then fails, and you get refund.failed.
pm_card_createDispute0259The payment succeeds, and a dispute as fraudulent is already open when the payment answers.
pm_card_createDisputeProductNotReceived2685The payment succeeds, and a dispute as product not received is already open when the payment answers.
pm_card_createDisputeInquiry1976The payment succeeds, and an inquiry is already open when the payment answers.

A refund is paid from your store's balance, funds still pending included. A card refund the balance does not cover is accepted with status pending and pending_reason insufficient_funds, and goes out once the balance covers it; a Pix refund the balance does not cover is refused with 400 balance_insufficient and refunds nothing. See Refund a payment.

A dispute arrives as a charge.dispute.created event. Treat the dispute id as opaque: store it as it comes and never parse it. See Handle disputes.

Names that are not test cards#

A test card name Fluveo does not know answers 404 resource_missing with param payment_method. Raw card numbers are refused: put the test name in payment_method, never a number in card[number]. A sk_live_ key never accepts a test name.

Type a card into the payment form#

On your own checkout and on the hosted checkout page, the buyer types the card into Fluveo's payment form. In test mode, type one of the numbers below with any future expiration date and any three-digit security code. Each number ends as the test card name beside it does. The numbers work only in the form: the API still refuses a card number in a request.

NumberSame asOutcome
4242 4242 4242 4242pm_card_visaThe payment succeeds.
5555 5555 5555 4444pm_card_mastercardThe payment succeeds.
4000 0000 0000 0002pm_card_visa_chargeDeclinedDeclined: card_declined with generic_decline.
4000 0000 0000 9995pm_card_visa_chargeDeclinedInsufficientFundsDeclined: card_declined with insufficient_funds.
4000 0000 0000 0127pm_card_chargeDeclinedIncorrectCvcDeclined: incorrect_cvc.
4000 0000 0000 3220pm_card_threeDSecure2RequiredAsks the buyer to authenticate, as under 3D Secure.
4000 0027 6000 3184pm_card_authenticationRequiredAsks the buyer to authenticate, as under 3D Secure.

Test Pix and Boleto#

MethodWhat a test payment does
PixCreating a test Pix answers requires_action with a pix_display_qr_code you can show. Fluveo's test bank then pays it as a real payer would, by the payer email: a local part ending in succeed_immediately is paid within seconds, one ending in expire_immediately, expire_with_delay or fill_never is never paid and expires at its own expires_at, any other email is paid about 3 minutes after the confirm, and a Pix with no email is never paid on its own. The page at hosted_instructions_url links to a test page that pays it now. See Pix.
BoletoCreating a test Boleto works the same way, with a boleto_display_details next action and the same payer emails; one that is never paid expires after its clearing period. The page at hosted_voucher_url links to a test page that pays it now. See Boleto.

Payer values for tests: CPF 12345678909, email ada@example.com (paid about 3 minutes after the confirm; use succeed_immediately@example.com to be paid within seconds), phone +5511999999999.

Test it#

  1. Create a PaymentIntent with payment_method_types[]=card, pm_card_visa and confirm=true. You get status succeeded.
  2. Do it again with pm_card_visa_chargeDeclined. You get 402, card_declined and generic_decline.
  3. Confirm the same PaymentIntent again with pm_card_visa. It succeeds.

Next#