Create transaction
Creates a single sales transaction. To create several transactions at once, see the Batch upload page.
Endpoint
Section titled “Endpoint”https://api.rapidchargeback.com/api/v1/transactionsAuthentication
Section titled “Authentication”Authorization: Basic base64(client_id:client_secret)Content-Type: application/jsonRequired fields
Section titled “Required fields”| Field | Type | Description |
|---|---|---|
merchant_id or merchant_ref | string | Send exactly one: merchant_id (the merchant’s UUID at Rapid, must belong to your company) or merchant_ref (the seller’s ID in your system, up to 100 characters, for channels/platforms with several sellers). If merchant_ref is unknown, the merchant is created automatically with merchant_name (optional, up to 255 characters; ignored when the merchant already exists). Sending both → 422 VALIDATION_ERROR. Your merchants and their merchant_id are in List merchants. |
external_id | string | Transaction ID in the source system |
amount | number | Transaction amount (must be positive) |
currency | string | ISO 4217 code with 3 uppercase letters (e.g. USD, BRL) |
transaction_date | string | Transaction date in ISO 8601 format (e.g. 2026-04-01T15:30:00Z) |
card_last4 | string | Last 4 digits of the card (exactly 4 numeric digits) |
items | array | At least 1 item (see the item fields below) |
Item fields
Section titled “Item fields”Required
Section titled “Required”| Field | Type | Description |
|---|---|---|
product_description | string | Product description (up to 1000 characters; above that the request fails) |
unit_price | number | Unit price |
Optional
Section titled “Optional”| Field | Type | Description |
|---|---|---|
product_name | string | Product name |
quantity | number | Quantity |
unit_of_measure | string | Unit of measure |
category | string | Product category |
Optional fields
Section titled “Optional fields”| Field | Type | Description |
|---|---|---|
external_source | string | Source system (default: custom) |
order_number | string | Order number |
transaction_id | string | Transaction ID in the payment gateway. See the note below |
arn | string | Acquirer Reference Number |
banknet_ref | string | Banknet reference (Mastercard) |
auth_code | string | Authorization code |
network | string | Card network: visa, mastercard, amex, discover, other |
card_bin | string | Card BIN (6 to 8 numeric digits) |
ip_address | string | Buyer’s IP address |
clearing_datetime | string | Clearing date (ISO 8601) |
mcc | string | Merchant Category Code |
eci | string | Electronic Commerce Indicator |
pos_entry_mode | string | POS entry mode |
descriptor | string | Billing descriptor |
correlation_id | string | Correlation ID |
device_id | string | Device ID (min. 15 characters) |
device_fingerprint | string | Device fingerprint (min. 20 characters) |
customer | object | Buyer data (see below) |
addresses | array | Shipping and/or billing addresses (see below) |
payments | array | Payment data (see below) |
refunds | array | Refund data (see below) |
Size limits
Section titled “Size limits”Every text field has a ceiling. Above it the response is 422 VALIDATION_ERROR naming the field, never a server error.
| Limit | Fields |
|---|---|
| 1000 | product_description |
| 255 | descriptor, merchant_name, product_name, device_fingerprint, street, reason (refund) |
| 200 | billing_name |
| 100 | external_id, order_number, transaction_id, arn, banknet_ref, correlation_id, merchant_ref, device_id, first_name, last_name, city, state, category |
| 64 | method_masked, reference_number |
| 45 | ip_address (fits IPv6) |
| 50 | external_source, auth_code, account_id |
| 32 | unit_of_measure |
| 30 | phone, postal_code, wallet_indicator |
| 20 | number (address) |
| 16 | payment_type |
| 10 | mcc, pos_entry_mode |
| 7 | card_expiry |
| 5 | eci |
| 2 | cvv2_presence_indicator, avs_result |
email follows the 255 limit and must have a valid format. currency, card_bin, card_last4, country and network have a fixed format, described in the fields table.
Note on transaction_id
Section titled “Note on transaction_id”It is optional, but fill it in whenever the charge went through a payment gateway: this is the field Rapid uses to link a future chargeback to the transaction. Send the charge identifier in the gateway, not your order number (that one is order_number).
If you use a gateway whose disputes reach Rapid and the field is empty, the chargeback is still received, but with no associated transaction: no history, no attached evidence and no authentication data, which is exactly the defense material. An equivalent alternative: send external_source with the gateway name and external_id with the charge id.
customer object (all optional)
Section titled “customer object (all optional)”| Field | Type | Description |
|---|---|---|
first_name | string | First name |
last_name | string | Last name |
email | string | Email (valid format) |
billing_name | string | Name on the card |
account_id | string | Buyer’s account ID in your system |
phone | string | Phone |
address object (inside the addresses array)
Section titled “address object (inside the addresses array)”| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | shipping or billing |
street | string | No | Street |
number | string | No | Number |
city | string | No | City |
state | string | No | State/Region |
postal_code | string | No | Postal code |
country | string | No | ISO 3166-1 country code, 2 or 3 uppercase letters (BR/BRA, US/USA). Alpha-3 recommended. |
Payment authentication fields (root, all optional)
Section titled “Payment authentication fields (root, all optional)”Inputs for fraud protection and 3-DS. The more you fill in, the stronger the deflection and the defense.
| Field | Type | Description |
|---|---|---|
cvv2_presence_indicator | string | CVV2 presence indicator in the authorization |
cvv2_result | string | CVV2 check result: M, N, P, S, U or Y, as it came in the authorization response |
avs_result | string | AVS result (address verification) |
cardholder_verification_approved | boolean | 3-DS/cardholder verification approved |
authentication_response_type | string | 3-DS authentication response type: attempt (attempt) or confirm (authentication confirmed) |
wallet_indicator | string | Digital wallet used (e.g. Apple Pay, Google Pay) |
Buyer account (inside customer, all optional)
Section titled “Buyer account (inside customer, all optional)”They say whether the purchase was made by a known account, and since when it exists. They are the strongest defense material in a fraud dispute: a buyer with an old account who was logged in is hard to dispute as “I do not recognize it”.
| Field | Type | Description |
|---|---|---|
registered_at | string (ISO 8601) | When the buyer’s account was created in your system |
registered_at_source | string | Where registered_at comes from: merchant_api (account record in your system) or client_declared (your statement, without that record) |
account_authenticated | boolean | The buyer was logged into the account when purchasing |
account_authenticated_source | string | How you know it: per_account (verified in this purchase) or onboarding_flag (your store’s rule, for example, every purchase requires login) |
account_authenticated_at | string (ISO 8601) | When the login happened |
auth_method | string | How the buyer logged in: password, otp, 2fa, biometric, oauth or other |
account_source_method | string | Where the account data comes from: merchant_api or client_declared |
checkout_type | string | How the purchase was made: guest (no account), authenticated (existing account, logged in) or registered_at_checkout (account created during the purchase) |
A value outside the lists responds 422 VALIDATION_ERROR.
payment object (all optional)
Section titled “payment object (all optional)”| Field | Type | Description |
|---|---|---|
payment_type | string | Payment type (credit, debit, pix, etc.) |
method_masked | string | Masked number |
matched_payment | boolean | Whether this payment was the one used (default: true) |
card_bin | string | BIN (6-8 digits) |
card_last4 | string | Last 4 digits (4 numeric digits) |
installments | integer | Number of installments |
card_expiry | string | Expiry (MM/YYYY) |
refund object
Section titled “refund object”| Field | Type | Required | Description |
|---|---|---|---|
amount | number | Yes | Refund amount (positive) |
currency | string | Yes | Currency (3 uppercase letters, ISO 4217) |
reference_number | string | No | Refund identifier |
reason | string | No | Refund reason |
refund_datetime | string | No | Refund date (ISO 8601) |
Validations
Section titled “Validations”transaction_datemust be in ISO 8601 with timezonecurrencymust be an ISO 4217 code (3 uppercase letters)amountmust be greater than zerocard_last4must have exactly 4 numeric digitscard_binmust have 6 to 8 numeric digitsdevice_idmust have at least 15 charactersdevice_fingerprintmust have at least 20 characters- The
external_source + external_idcombination cannot duplicate an existing transaction of your company
Warnings
Section titled “Warnings”The API returns notices (without blocking creation) when important optional fields are missing:
| When | Notice |
|---|---|
No card_bin | card_bin missing: reduces match accuracy |
No order_number | order_number missing: recommended to identify the order in dispute responses |
No ip_address, device_id and device_fingerprint | ip_address, device_id and device_fingerprint missing: recommended, fraud protection relies on them |
One of the three identifiers is enough to clear the last notice: the IP is not required. And there is no address notice on purpose: whoever sells digital goods should not send a shipping address (see fraud protection).
The warnings key only shows up in the response when there is at least one notice. Do not count on warnings: [].
Request example
Section titled “Request example”The credentials come from environment variables (RAPID_CLIENT_ID and RAPID_CLIENT_SECRET), never written in the code.
curl -X POST https://api.rapidchargeback.com/api/v1/transactions \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" \ -H "Content-Type: application/json" \ -d '{ "merchant_id": "00000000-0000-0000-0000-000000000001", "external_source": "shopify", "external_id": "TXN-2026-001", "transaction_date": "2026-04-01T15:30:00Z", "amount": 150.00, "currency": "USD", "card_last4": "4242", "card_bin": "424242", "order_number": "ORD-001", "auth_code": "AUTH999", "network": "visa", "descriptor": "LOJA EXEMPLO", "ip_address": "203.0.113.10", "items": [ { "product_description": "Assinatura Premium - Mensal", "product_name": "Plano Premium", "quantity": 1, "unit_price": 150.00 } ], "customer": { "first_name": "João", "last_name": "Silva", "email": "joao@exemplo.com" }, "addresses": [ { "type": "shipping", "street": "Rua das Flores", "number": "123", "city": "São Paulo", "state": "SP", "postal_code": "01001000", "country": "BRA" } ] }'const credentials = Buffer.from(`${process.env.RAPID_CLIENT_ID}:${process.env.RAPID_CLIENT_SECRET}`).toString('base64')
const response = await fetch('https://api.rapidchargeback.com/api/v1/transactions', { method: 'POST', headers: { Authorization: `Basic ${credentials}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ merchant_id: '00000000-0000-0000-0000-000000000001', external_source: 'shopify', external_id: 'TXN-2026-001', transaction_date: '2026-04-01T15:30:00Z', amount: 150.0, currency: 'USD', card_last4: '4242', card_bin: '424242', order_number: 'ORD-001', auth_code: 'AUTH999', network: 'visa', descriptor: 'LOJA EXEMPLO', ip_address: '203.0.113.10', items: [ { product_description: 'Assinatura Premium - Mensal', product_name: 'Plano Premium', quantity: 1, unit_price: 150.0, }, ], customer: { first_name: 'João', last_name: 'Silva', email: 'joao@exemplo.com', }, addresses: [ { type: 'shipping', street: 'Rua das Flores', number: '123', city: 'São Paulo', state: 'SP', postal_code: '01001000', country: 'BRA', }, ], }),})
const body = await response.json()if (!response.ok) throw new Error(`${response.status} ${body.error.code}: ${body.error.message}`)
console.log('Transaction created:', body.data.id)for (const warning of body.warnings ?? []) console.warn('Warning:', warning)import os
import requests
response = requests.post( "https://api.rapidchargeback.com/api/v1/transactions", auth=(os.environ["RAPID_CLIENT_ID"], os.environ["RAPID_CLIENT_SECRET"]), json={ "merchant_id": "00000000-0000-0000-0000-000000000001", "external_source": "shopify", "external_id": "TXN-2026-001", "transaction_date": "2026-04-01T15:30:00Z", "amount": 150.00, "currency": "USD", "card_last4": "4242", "card_bin": "424242", "order_number": "ORD-001", "auth_code": "AUTH999", "network": "visa", "descriptor": "LOJA EXEMPLO", "ip_address": "203.0.113.10", "items": [ { "product_description": "Assinatura Premium - Mensal", "product_name": "Plano Premium", "quantity": 1, "unit_price": 150.00, } ], "customer": { "first_name": "João", "last_name": "Silva", "email": "joao@exemplo.com", }, "addresses": [ { "type": "shipping", "street": "Rua das Flores", "number": "123", "city": "São Paulo", "state": "SP", "postal_code": "01001000", "country": "BRA", } ], }, timeout=30,)
body = response.json()if not response.ok: raise RuntimeError(f"{response.status_code} {body['error']['code']}: {body['error']['message']}")
print("Transaction created:", body["data"]["id"])for warning in body.get("warnings", []): print("Warning:", warning)<?php$transaction = [ 'merchant_id' => '00000000-0000-0000-0000-000000000001', 'external_source' => 'shopify', 'external_id' => 'TXN-2026-001', 'transaction_date' => '2026-04-01T15:30:00Z', 'amount' => 150.00, 'currency' => 'USD', 'card_last4' => '4242', 'card_bin' => '424242', 'order_number' => 'ORD-001', 'auth_code' => 'AUTH999', 'network' => 'visa', 'descriptor' => 'LOJA EXEMPLO', 'ip_address' => '203.0.113.10', 'items' => [ [ 'product_description' => 'Assinatura Premium - Mensal', 'product_name' => 'Plano Premium', 'quantity' => 1, 'unit_price' => 150.00, ], ], 'customer' => [ 'first_name' => 'João', 'last_name' => 'Silva', 'email' => 'joao@exemplo.com', ], 'addresses' => [ [ 'type' => 'shipping', 'street' => 'Rua das Flores', 'number' => '123', 'city' => 'São Paulo', 'state' => 'SP', 'postal_code' => '01001000', 'country' => 'BRA', ], ],];
$ch = curl_init('https://api.rapidchargeback.com/api/v1/transactions');curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_USERPWD => getenv('RAPID_CLIENT_ID') . ':' . getenv('RAPID_CLIENT_SECRET'), CURLOPT_HTTPHEADER => ['Content-Type: application/json'], CURLOPT_POSTFIELDS => json_encode($transaction), CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 30,]);
$raw = curl_exec($ch);if ($raw === false) { throw new RuntimeException('Network error: ' . curl_error($ch));}$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);$body = json_decode($raw, true);
if ($status >= 400) { throw new RuntimeException("$status {$body['error']['code']}: {$body['error']['message']}");}
echo 'Transaction created: ', $body['data']['id'], PHP_EOL;foreach ($body['warnings'] ?? [] as $warning) { echo 'Warning: ', $warning, PHP_EOL;}Response examples
Section titled “Response examples”Success
Section titled “Success”{ "data": { "id": "00000000-0000-0000-0000-000000000042", "company_id": "...", "merchant_id": "00000000-0000-0000-0000-000000000001", "external_id": "TXN-2026-001", "amount": 150.00, "currency": "USD", "transaction_date": "2026-04-01T15:30:00.000Z", "card_last4": "4242", "created_at": "2026-04-01T15:31:00.000Z", "transaction_items": [...], "transaction_customers": [...], "transaction_addresses": [...] }}Duplicate
Section titled “Duplicate”{ "error": { "code": "TRANSACTION_DUPLICATE", "message": "Transaction already exists" }}Validation error
Section titled “Validation error”{ "error": { "code": "VALIDATION_ERROR", "message": "card_last4 must be exactly 4 digits" }}