Create Card
curl --request POST \
--url https://api.fyatu.com/api/v3/cards \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"cardholderId": "ch_a1b2c3d4e5f6",
"name": "ALICE EXAMPLE",
"amount": 100,
"productId": "MCUSD1"
}
'import requests
url = "https://api.fyatu.com/api/v3/cards"
payload = {
"cardholderId": "ch_a1b2c3d4e5f6",
"name": "ALICE EXAMPLE",
"amount": 100,
"productId": "MCUSD1"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
cardholderId: 'ch_a1b2c3d4e5f6',
name: 'ALICE EXAMPLE',
amount: 100,
productId: 'MCUSD1'
})
};
fetch('https://api.fyatu.com/api/v3/cards', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.fyatu.com/api/v3/cards",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'cardholderId' => 'ch_a1b2c3d4e5f6',
'name' => 'ALICE EXAMPLE',
'amount' => 100,
'productId' => 'MCUSD1'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.fyatu.com/api/v3/cards"
payload := strings.NewReader("{\n \"cardholderId\": \"ch_a1b2c3d4e5f6\",\n \"name\": \"ALICE EXAMPLE\",\n \"amount\": 100,\n \"productId\": \"MCUSD1\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.fyatu.com/api/v3/cards")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"cardholderId\": \"ch_a1b2c3d4e5f6\",\n \"name\": \"ALICE EXAMPLE\",\n \"amount\": 100,\n \"productId\": \"MCUSD1\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.fyatu.com/api/v3/cards")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"cardholderId\": \"ch_a1b2c3d4e5f6\",\n \"name\": \"ALICE EXAMPLE\",\n \"amount\": 100,\n \"productId\": \"MCUSD1\"\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"status": 201,
"message": "Card created successfully",
"data": {
"id": "crd_8f3a2b1c4d5e6f7890abcdef12345678",
"cardholderId": "ch_1a2b3c4d5e6f7890abcdef1234567890",
"name": "JAMES WILSON",
"last4": "4829",
"maskedNumber": "****4829",
"expiryDate": "01/2030",
"brand": "MASTERCARD",
"currency": "USD",
"status": "ACTIVE",
"initialBalance": 100,
"createdAt": "2026-01-17 10:00:00"
},
"meta": {
"requestId": "req_a1b2c3d4e5f6",
"timestamp": "2026-01-17T10:00:00+00:00"
}
}Cards
Create Card
Issue a new virtual Mastercard or Visa prepaid card programmatically. Specify cardholder, amount, and product. POST /cards.
POST
/
cards
Create Card
curl --request POST \
--url https://api.fyatu.com/api/v3/cards \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"cardholderId": "ch_a1b2c3d4e5f6",
"name": "ALICE EXAMPLE",
"amount": 100,
"productId": "MCUSD1"
}
'import requests
url = "https://api.fyatu.com/api/v3/cards"
payload = {
"cardholderId": "ch_a1b2c3d4e5f6",
"name": "ALICE EXAMPLE",
"amount": 100,
"productId": "MCUSD1"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
cardholderId: 'ch_a1b2c3d4e5f6',
name: 'ALICE EXAMPLE',
amount: 100,
productId: 'MCUSD1'
})
};
fetch('https://api.fyatu.com/api/v3/cards', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.fyatu.com/api/v3/cards",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'cardholderId' => 'ch_a1b2c3d4e5f6',
'name' => 'ALICE EXAMPLE',
'amount' => 100,
'productId' => 'MCUSD1'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.fyatu.com/api/v3/cards"
payload := strings.NewReader("{\n \"cardholderId\": \"ch_a1b2c3d4e5f6\",\n \"name\": \"ALICE EXAMPLE\",\n \"amount\": 100,\n \"productId\": \"MCUSD1\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.fyatu.com/api/v3/cards")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"cardholderId\": \"ch_a1b2c3d4e5f6\",\n \"name\": \"ALICE EXAMPLE\",\n \"amount\": 100,\n \"productId\": \"MCUSD1\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.fyatu.com/api/v3/cards")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"cardholderId\": \"ch_a1b2c3d4e5f6\",\n \"name\": \"ALICE EXAMPLE\",\n \"amount\": 100,\n \"productId\": \"MCUSD1\"\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"status": 201,
"message": "Card created successfully",
"data": {
"id": "crd_8f3a2b1c4d5e6f7890abcdef12345678",
"cardholderId": "ch_1a2b3c4d5e6f7890abcdef1234567890",
"name": "JAMES WILSON",
"last4": "4829",
"maskedNumber": "****4829",
"expiryDate": "01/2030",
"brand": "MASTERCARD",
"currency": "USD",
"status": "ACTIVE",
"initialBalance": 100,
"createdAt": "2026-01-17 10:00:00"
},
"meta": {
"requestId": "req_a1b2c3d4e5f6",
"timestamp": "2026-01-17T10:00:00+00:00"
}
}Overview
Issue a new virtual card to a cardholder. The cardholder must have verified KYC status and your business wallet must have sufficient balance for the card amount plus fees.Card creation is asynchronous. A successful response means the request was accepted; the card may be returned with status
CREATING and no PAN yet, and is confirmed only when its status becomes ACTIVE. If the response is delayed, the card is still being provisioned — poll Get Card until status is ACTIVE rather than treating the immediate response as final. A card that fails to provision does not activate and any held balance is released.Prerequisites
- Verified Cardholder: The cardholder must exist and have
status: ACTIVE - Sufficient Balance: Wallet must cover:
amount (in USD) + issuanceFee - Active Application: Your app must be in
ACTIVEstatus
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
cardholderId | string | Yes | ID of the cardholder to issue card to |
amount | number | Yes | Initial funding amount in product currency (minimum $5 or €5) |
name | string | No | Name on card (defaults to cardholder name) |
productId | string | No | Card product to issue (from List Products). Defaults to the product marked isDefault: true |
spendingLimit | integer | No | Deprecated — Use productId instead. Monthly spending limit: 5000 or 10000 (default: 5000) |
Deprecation Notice: The
spendingLimit field is deprecated and will be removed in a future version. Use productId to select the card product, which determines the spending limit, brand, and currency automatically. If both productId and spendingLimit are provided, productId takes precedence.Example Usage
<?php
// Recommended: use productId
$data = [
'cardholderId' => 'ch_a1b2c3d4e5f6',
'amount' => 100.00,
'name' => 'ALICE EXAMPLE',
'productId' => 'MCUSD1'
];
$ch = curl_init('https://api.fyatu.com/api/v3/cards');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $accessToken,
'Content-Type: application/json'
],
CURLOPT_POSTFIELDS => json_encode($data)
]);
$response = curl_exec($ch);
$result = json_decode($response, true);
if ($result['success']) {
echo "Card created: " . $result['data']['id'] . "\n";
echo "Brand: " . $result['data']['brand'] . "\n";
echo "Currency: " . $result['data']['currency'] . "\n";
echo "Balance: " . $result['data']['initialBalance'] . "\n";
}
// Recommended: use productId
const response = await fetch('https://api.fyatu.com/api/v3/cards', {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
cardholderId: 'ch_a1b2c3d4e5f6',
amount: 100.00,
name: 'ALICE EXAMPLE',
productId: 'MCUSD1'
})
});
const result = await response.json();
if (result.success) {
console.log('Card created:', result.data.id);
console.log('Brand:', result.data.brand);
console.log('Currency:', result.data.currency);
}
EUR Card Example
When issuing a EUR-denominated card, theamount is specified in EUR. Your wallet (USD) is debited the equivalent in USD at the current exchange rate.
const response = await fetch('https://api.fyatu.com/api/v3/cards', {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
cardholderId: 'ch_a1b2c3d4e5f6',
amount: 100.00, // €100 EUR
productId: 'MCEUR1'
})
});
// Response:
// {
// "data": {
// "id": "crd_...",
// "brand": "MASTERCARD",
// "currency": "EUR",
// "initialBalance": 100.00 // €100 on card
// }
// }
// Wallet debited: ~$108.70 USD (100 / EUR rate) + issuance fee
Response Fields
| Field | Type | Description |
|---|---|---|
id | string | Unique card identifier |
cardholderId | string | The cardholder this card belongs to |
name | string | Name printed on the card |
last4 | string | null | Last 4 digits of the card number. null while the card is still provisioning (CREATING/PROCESSING) |
maskedNumber | string | null | Masked card number (e.g., ****4829). null while the card is still provisioning (CREATING/PROCESSING) |
expiryDate | string | null | Card expiration date (MM/YY). null while the card is still provisioning (CREATING/PROCESSING) |
brand | string | Card brand: MASTERCARD or VISA |
currency | string | Card currency: USD or EUR |
status | string | Card status: ACTIVE, CREATING, or PROCESSING (see below) |
initialBalance | number | Initial funding amount in card currency |
createdAt | string | Card creation timestamp |
Card Status on Creation
Cards are provisioned asynchronously by the card provider. When a card is not ready in the create response, the API returns immediately withstatus: CREATING (or PROCESSING on legacy products) and card details (last4, maskedNumber, expiryDate) will be null. Provisioning usually completes within seconds but can take up to ~1 hour.
Once the card is ready, its status becomes ACTIVE and the full card details (last4, maskedNumber, expiryDate) are populated. If provisioning fails, the card does not activate and any held balance is released.
| Status | Meaning |
|---|---|
ACTIVE | Card is ready to use immediately |
CREATING | Card is being provisioned by the provider — poll GET /cards/{cardId} until ACTIVE |
PROCESSING | Legacy async status (same meaning as CREATING) — poll GET /cards/{cardId} |
Card creation is confirmed by the
status field, not by a webhook — poll Get Card until status is ACTIVE (provisioning usually completes within seconds). Funding, unloading, and the rest of the card lifecycle each have their own webhook events.Error Responses
| Error Code | Description |
|---|---|
APP_INACTIVE | Application is not active |
CARDHOLDER_INACTIVE | Cardholder is not active (KYC not verified) |
INSUFFICIENT_BALANCE | Business wallet balance is too low |
PRODUCT_NOT_FOUND | Card product not found |
PRODUCT_INACTIVE | Card product is currently inactive |
PRODUCT_UNAVAILABLE | Card product is temporarily unavailable for new issuance |
RATE_UNAVAILABLE | Unable to fetch exchange rate for EUR products |
HOLD_FAILED | Failed to hold balance from business wallet |
PROVIDER_NOT_CONFIGURED | Card provider account not configured |
CARD_CREATION_FAILED | Failed to create card at the bank partner |
CARDHOLDER_REGISTRATION_FAILED | Failed to register cardholder with card provider |
CARDHOLDER_RESTRICTED | Cardholder has been restricted by the card provider |
BUSINESS_KYB_REQUIRED | Business KYB verification incomplete |
Use the List Products endpoint to discover available card products and their fees before creating a card.
Authorizations
JWT access token obtained from /auth/token
Body
application/json
ID of the cardholder to issue card to
Initial funding amount in product currency (minimum $5 or €5)
Required range:
x >= 5Name on card (defaults to cardholder name if not provided)
Minimum string length:
4Card product to issue (from List Products endpoint). Determines brand, currency, and spending limit. Defaults to the product marked isDefault if not provided.
Example:
"MCUSD1"
Deprecated — Use productId instead. Monthly spending limit in USD.
Available options:
5000, 10000 
