Create a product
curl --request POST \
--url https://api.fyatu.com/api/v3.20/programs/{id}/products \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Prepaid VISA Consumer 12m",
"scheme": "VISA",
"binCode": "SG-VISA-V-01",
"cardType": "CONSUMER",
"features": {
"has3DS": true,
"hasApplePay": true,
"hasGooglePay": true,
"hasJIT": false,
"hasSpendControl": false,
"hasMccControl": false
},
"controls": {
"isReloadable": false,
"isOneTimeUse": false,
"cardTTLMonths": 12,
"maxCardsPerCardholder": 5,
"spendingLimit": 1000,
"spendingPeriod": "TRANSAMOUNT"
}
}
'import requests
url = "https://api.fyatu.com/api/v3.20/programs/{id}/products"
payload = {
"name": "Prepaid VISA Consumer 12m",
"scheme": "VISA",
"binCode": "SG-VISA-V-01",
"cardType": "CONSUMER",
"features": {
"has3DS": True,
"hasApplePay": True,
"hasGooglePay": True,
"hasJIT": False,
"hasSpendControl": False,
"hasMccControl": False
},
"controls": {
"isReloadable": False,
"isOneTimeUse": False,
"cardTTLMonths": 12,
"maxCardsPerCardholder": 5,
"spendingLimit": 1000,
"spendingPeriod": "TRANSAMOUNT"
}
}
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({
name: 'Prepaid VISA Consumer 12m',
scheme: 'VISA',
binCode: 'SG-VISA-V-01',
cardType: 'CONSUMER',
features: {
has3DS: true,
hasApplePay: true,
hasGooglePay: true,
hasJIT: false,
hasSpendControl: false,
hasMccControl: false
},
controls: {
isReloadable: false,
isOneTimeUse: false,
cardTTLMonths: 12,
maxCardsPerCardholder: 5,
spendingLimit: 1000,
spendingPeriod: 'TRANSAMOUNT'
}
})
};
fetch('https://api.fyatu.com/api/v3.20/programs/{id}/products', 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.20/programs/{id}/products",
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([
'name' => 'Prepaid VISA Consumer 12m',
'scheme' => 'VISA',
'binCode' => 'SG-VISA-V-01',
'cardType' => 'CONSUMER',
'features' => [
'has3DS' => true,
'hasApplePay' => true,
'hasGooglePay' => true,
'hasJIT' => false,
'hasSpendControl' => false,
'hasMccControl' => false
],
'controls' => [
'isReloadable' => false,
'isOneTimeUse' => false,
'cardTTLMonths' => 12,
'maxCardsPerCardholder' => 5,
'spendingLimit' => 1000,
'spendingPeriod' => 'TRANSAMOUNT'
]
]),
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.20/programs/{id}/products"
payload := strings.NewReader("{\n \"name\": \"Prepaid VISA Consumer 12m\",\n \"scheme\": \"VISA\",\n \"binCode\": \"SG-VISA-V-01\",\n \"cardType\": \"CONSUMER\",\n \"features\": {\n \"has3DS\": true,\n \"hasApplePay\": true,\n \"hasGooglePay\": true,\n \"hasJIT\": false,\n \"hasSpendControl\": false,\n \"hasMccControl\": false\n },\n \"controls\": {\n \"isReloadable\": false,\n \"isOneTimeUse\": false,\n \"cardTTLMonths\": 12,\n \"maxCardsPerCardholder\": 5,\n \"spendingLimit\": 1000,\n \"spendingPeriod\": \"TRANSAMOUNT\"\n }\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.20/programs/{id}/products")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Prepaid VISA Consumer 12m\",\n \"scheme\": \"VISA\",\n \"binCode\": \"SG-VISA-V-01\",\n \"cardType\": \"CONSUMER\",\n \"features\": {\n \"has3DS\": true,\n \"hasApplePay\": true,\n \"hasGooglePay\": true,\n \"hasJIT\": false,\n \"hasSpendControl\": false,\n \"hasMccControl\": false\n },\n \"controls\": {\n \"isReloadable\": false,\n \"isOneTimeUse\": false,\n \"cardTTLMonths\": 12,\n \"maxCardsPerCardholder\": 5,\n \"spendingLimit\": 1000,\n \"spendingPeriod\": \"TRANSAMOUNT\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.fyatu.com/api/v3.20/programs/{id}/products")
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 \"name\": \"Prepaid VISA Consumer 12m\",\n \"scheme\": \"VISA\",\n \"binCode\": \"SG-VISA-V-01\",\n \"cardType\": \"CONSUMER\",\n \"features\": {\n \"has3DS\": true,\n \"hasApplePay\": true,\n \"hasGooglePay\": true,\n \"hasJIT\": false,\n \"hasSpendControl\": false,\n \"hasMccControl\": false\n },\n \"controls\": {\n \"isReloadable\": false,\n \"isOneTimeUse\": false,\n \"cardTTLMonths\": 12,\n \"maxCardsPerCardholder\": 5,\n \"spendingLimit\": 1000,\n \"spendingPeriod\": \"TRANSAMOUNT\"\n }\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"status": 201,
"message": "Product created",
"data": {
"productId": "prd_01HXYZ1111ABCDEF0002",
"programId": "prg_01HXYZ9876ABCDEF0000",
"name": "Prepaid VISA Consumer 12m",
"scheme": "VISA",
"cardType": "CONSUMER",
"features": {
"has3DS": true,
"hasApplePay": true,
"hasGooglePay": true,
"hasJIT": false,
"hasSpendControl": false,
"hasMccControl": false
},
"controls": {
"isReloadable": false,
"isOneTimeUse": false,
"cardTTLMonths": 12,
"maxCardsPerCardholder": 1
},
"status": "ACTIVE",
"createdAt": "2026-05-26T11:00:00Z"
},
"meta": {
"requestId": "req_a1b2c3d4e5f6a7b8c9d0e1f2",
"platform": "Fyatu CaaS",
"timestamp": "2026-05-26T11:00:00Z"
}
}Products
Create Product
Create a new card product within a program. POST /programs//products. Requires accounts:write scope.
POST
/
programs
/
{id}
/
products
Create a product
curl --request POST \
--url https://api.fyatu.com/api/v3.20/programs/{id}/products \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Prepaid VISA Consumer 12m",
"scheme": "VISA",
"binCode": "SG-VISA-V-01",
"cardType": "CONSUMER",
"features": {
"has3DS": true,
"hasApplePay": true,
"hasGooglePay": true,
"hasJIT": false,
"hasSpendControl": false,
"hasMccControl": false
},
"controls": {
"isReloadable": false,
"isOneTimeUse": false,
"cardTTLMonths": 12,
"maxCardsPerCardholder": 5,
"spendingLimit": 1000,
"spendingPeriod": "TRANSAMOUNT"
}
}
'import requests
url = "https://api.fyatu.com/api/v3.20/programs/{id}/products"
payload = {
"name": "Prepaid VISA Consumer 12m",
"scheme": "VISA",
"binCode": "SG-VISA-V-01",
"cardType": "CONSUMER",
"features": {
"has3DS": True,
"hasApplePay": True,
"hasGooglePay": True,
"hasJIT": False,
"hasSpendControl": False,
"hasMccControl": False
},
"controls": {
"isReloadable": False,
"isOneTimeUse": False,
"cardTTLMonths": 12,
"maxCardsPerCardholder": 5,
"spendingLimit": 1000,
"spendingPeriod": "TRANSAMOUNT"
}
}
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({
name: 'Prepaid VISA Consumer 12m',
scheme: 'VISA',
binCode: 'SG-VISA-V-01',
cardType: 'CONSUMER',
features: {
has3DS: true,
hasApplePay: true,
hasGooglePay: true,
hasJIT: false,
hasSpendControl: false,
hasMccControl: false
},
controls: {
isReloadable: false,
isOneTimeUse: false,
cardTTLMonths: 12,
maxCardsPerCardholder: 5,
spendingLimit: 1000,
spendingPeriod: 'TRANSAMOUNT'
}
})
};
fetch('https://api.fyatu.com/api/v3.20/programs/{id}/products', 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.20/programs/{id}/products",
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([
'name' => 'Prepaid VISA Consumer 12m',
'scheme' => 'VISA',
'binCode' => 'SG-VISA-V-01',
'cardType' => 'CONSUMER',
'features' => [
'has3DS' => true,
'hasApplePay' => true,
'hasGooglePay' => true,
'hasJIT' => false,
'hasSpendControl' => false,
'hasMccControl' => false
],
'controls' => [
'isReloadable' => false,
'isOneTimeUse' => false,
'cardTTLMonths' => 12,
'maxCardsPerCardholder' => 5,
'spendingLimit' => 1000,
'spendingPeriod' => 'TRANSAMOUNT'
]
]),
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.20/programs/{id}/products"
payload := strings.NewReader("{\n \"name\": \"Prepaid VISA Consumer 12m\",\n \"scheme\": \"VISA\",\n \"binCode\": \"SG-VISA-V-01\",\n \"cardType\": \"CONSUMER\",\n \"features\": {\n \"has3DS\": true,\n \"hasApplePay\": true,\n \"hasGooglePay\": true,\n \"hasJIT\": false,\n \"hasSpendControl\": false,\n \"hasMccControl\": false\n },\n \"controls\": {\n \"isReloadable\": false,\n \"isOneTimeUse\": false,\n \"cardTTLMonths\": 12,\n \"maxCardsPerCardholder\": 5,\n \"spendingLimit\": 1000,\n \"spendingPeriod\": \"TRANSAMOUNT\"\n }\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.20/programs/{id}/products")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Prepaid VISA Consumer 12m\",\n \"scheme\": \"VISA\",\n \"binCode\": \"SG-VISA-V-01\",\n \"cardType\": \"CONSUMER\",\n \"features\": {\n \"has3DS\": true,\n \"hasApplePay\": true,\n \"hasGooglePay\": true,\n \"hasJIT\": false,\n \"hasSpendControl\": false,\n \"hasMccControl\": false\n },\n \"controls\": {\n \"isReloadable\": false,\n \"isOneTimeUse\": false,\n \"cardTTLMonths\": 12,\n \"maxCardsPerCardholder\": 5,\n \"spendingLimit\": 1000,\n \"spendingPeriod\": \"TRANSAMOUNT\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.fyatu.com/api/v3.20/programs/{id}/products")
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 \"name\": \"Prepaid VISA Consumer 12m\",\n \"scheme\": \"VISA\",\n \"binCode\": \"SG-VISA-V-01\",\n \"cardType\": \"CONSUMER\",\n \"features\": {\n \"has3DS\": true,\n \"hasApplePay\": true,\n \"hasGooglePay\": true,\n \"hasJIT\": false,\n \"hasSpendControl\": false,\n \"hasMccControl\": false\n },\n \"controls\": {\n \"isReloadable\": false,\n \"isOneTimeUse\": false,\n \"cardTTLMonths\": 12,\n \"maxCardsPerCardholder\": 5,\n \"spendingLimit\": 1000,\n \"spendingPeriod\": \"TRANSAMOUNT\"\n }\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"status": 201,
"message": "Product created",
"data": {
"productId": "prd_01HXYZ1111ABCDEF0002",
"programId": "prg_01HXYZ9876ABCDEF0000",
"name": "Prepaid VISA Consumer 12m",
"scheme": "VISA",
"cardType": "CONSUMER",
"features": {
"has3DS": true,
"hasApplePay": true,
"hasGooglePay": true,
"hasJIT": false,
"hasSpendControl": false,
"hasMccControl": false
},
"controls": {
"isReloadable": false,
"isOneTimeUse": false,
"cardTTLMonths": 12,
"maxCardsPerCardholder": 1
},
"status": "ACTIVE",
"createdAt": "2026-05-26T11:00:00Z"
},
"meta": {
"requestId": "req_a1b2c3d4e5f6a7b8c9d0e1f2",
"platform": "Fyatu CaaS",
"timestamp": "2026-05-26T11:00:00Z"
}
}Overview
Creates a new card product under an existing program. A Card Product defines the scheme (VISA or Mastercard), card type (Consumer or Corporate), the feature set (3DS, Apple Pay, JIT), and the lifecycle controls (reloadability, one-time use, TTL, spend limits, cardholder card limits). Once created, the productproductId is passed to POST /cards to issue cards under that configuration.
Products are shared resources — always written to the LIVE database regardless of whether your API key is LIVE or SANDBOX.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
programId | string | The program to create the product under (prefix prg_) |
Request Body
Required
| Field | Type | Description |
|---|---|---|
name | string | Human-readable product name (e.g. "Standard VISA Consumer") |
scheme | string | Card network — VISA or MASTERCARD. Must match a scheme enabled on your program. Required only when binCode is omitted — a BIN already determines the scheme |
Optional — Choosing a BIN
| Field | Type | Default | Description |
|---|---|---|---|
binCode | string | — | Issue this product against a specific BIN. Determines the issuing country, scheme, and which wallets the card can support |
binCode and nothing changes: the product is created from scheme exactly as before. Supply
it to choose where cards are issued and which capabilities they carry.
A BIN’s capabilities are fixed by the issuer — they cannot be enabled per product. Requesting a
feature the BIN does not carry returns 400 FEATURE_NOT_SUPPORTED_BY_BIN rather than creating a
product that promises something its cards can never deliver.
| BIN code | BIN | Scheme | Issued in | Use case | Cardholder KYC | Wallets |
|---|---|---|---|---|---|---|
US-VISA-V-01 | 493724 | Visa | United States | Corporate | Not required | Google Pay, 3DS |
US-MC-V-02 | 537100 | Mastercard | United States | Corporate | Not required | Apple Pay, Google Pay, 3DS |
SG-VISA-V-01 | 49372410 | Visa | Singapore | Corporate | Not required | Apple Pay, Google Pay, 3DS |
SG-VISA-V-02 | 40433705 | Visa | Singapore | Consumer | Required | Apple Pay, Google Pay, 3DS |
HK-VISA-V-01 | 49387519 | Visa | Hong Kong | Consumer | Required | Apple Pay, Google Pay, 3DS |
HK-MC-V-01 | 524013 | Mastercard | Hong Kong | Consumer | Required | Apple Pay, Google Pay, 3DS |
binCode is returned on every product read, so you can always ask which BIN a product issues from.
It is null for products created before BINs were selectable.
US-VISA-V-01 is the one BIN without Apple Pay. Requesting features.hasApplePay against it
returns 400 FEATURE_NOT_SUPPORTED_BY_BIN — use US-MC-V-02 for a US card that needs Apple Pay.The three Consumer BINs require the cardholder to have completed KYC before a card can be
issued. The Corporate BINs do not.
Optional — Card Type
| Field | Type | Default | Description |
|---|---|---|---|
cardType | string | CONSUMER | CONSUMER or CORPORATE |
Optional — features Object
Features are validated against what your program catalog allows. Requesting a feature not enabled on your program returns 400 FEATURE_NOT_ALLOWED.
| Field | Type | Default | Description |
|---|---|---|---|
features.has3DS | boolean | false | Enable 3D Secure authentication |
features.hasApplePay | boolean | false | Enable Apple Pay tokenisation |
features.hasGooglePay | boolean | false | Enable Google Pay tokenisation |
features.hasJIT | boolean | false | Enable Just-In-Time funding |
features.hasSpendControl | boolean | false | Enable per-card spend limits |
features.hasMccControl | boolean | false | Enable MCC (merchant category) allow/block rules |
Optional — controls Object
Controls govern card lifecycle rules and are enforced at issuance and funding time.
| Field | Type | Default | Description |
|---|---|---|---|
controls.isReloadable | boolean | true | When false, POST /cards/{id}/fund is rejected for every card under this product. Set to false for one-load prepaid or gift-card style products |
controls.isOneTimeUse | boolean | false | When true, a card is automatically terminated after its first settled transaction. Ideal for single-purchase virtual cards |
controls.cardTTLMonths | integer | null | 36 | Cap on card validity in months from issuance. If the card scheme grants a longer expiry, it is capped at this value |
controls.maxCardsPerCardholder | integer | null | 5 | Maximum simultaneously active (non-TERMINATED) cards a cardholder may hold under this product. Attempting to issue a card beyond this limit returns 409 CARDHOLDER_CARD_LIMIT_EXCEEDED |
controls.spendingLimit | number | 1000 | Maximum spend amount per spendingPeriod. Expressed in the program’s currency (USD) |
controls.spendingPeriod | string | TRANSAMOUNT | The period over which spendingLimit is enforced — TRANSAMOUNT, DAILY, WEEKLY, or MONTHLY |
Example
curl -X POST https://api.fyatu.com/api/v3.20/programs/prg_01HXYZ9876ABCDEF0000/products \
-H "Authorization: Bearer $FYATU_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Prepaid VISA Consumer 12m",
"scheme": "VISA",
"cardType": "CONSUMER",
"features": {
"has3DS": true,
"hasApplePay": true,
"hasGooglePay": true,
"hasJIT": false,
"hasSpendControl": false,
"hasMccControl": false
},
"controls": {
"isReloadable": false,
"isOneTimeUse": false,
"cardTTLMonths": 12,
"maxCardsPerCardholder": 5,
"spendingLimit": 1000,
"spendingPeriod": "TRANSAMOUNT"
}
}'
const resp = await fetch(
'https://api.fyatu.com/api/v3.20/programs/prg_01HXYZ9876ABCDEF0000/products',
{
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.FYATU_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Prepaid VISA Consumer 12m',
scheme: 'VISA',
cardType: 'CONSUMER',
features: {
has3DS: true,
hasApplePay: true,
hasGooglePay: true,
hasJIT: false,
hasSpendControl: false,
hasMccControl: false
},
controls: {
isReloadable: false,
isOneTimeUse: false,
cardTTLMonths: 12,
maxCardsPerCardholder: 5,
spendingLimit: 1000,
spendingPeriod: 'TRANSAMOUNT'
}
})
}
);
const { data: product } = await resp.json();
console.log('Created:', product.productId, '| TTL:', product.controls.cardTTLMonths, 'months');
import os, requests
resp = requests.post(
'https://api.fyatu.com/api/v3.20/programs/prg_01HXYZ9876ABCDEF0000/products',
headers={'Authorization': f'Bearer {os.environ["FYATU_API_KEY"]}'},
json={
'name': 'Prepaid VISA Consumer 12m',
'scheme': 'VISA',
'cardType': 'CONSUMER',
'features': {
'has3DS': True,
'hasApplePay': True,
'hasGooglePay': True,
'hasJIT': False,
'hasSpendControl': False,
'hasMccControl': False
},
'controls': {
'isReloadable': False,
'isOneTimeUse': False,
'cardTTLMonths': 12,
'maxCardsPerCardholder': 5,
'spendingLimit': 1000,
'spendingPeriod': 'TRANSAMOUNT'
}
}
)
product = resp.json()['data']
print(product['productId'], product['controls']['cardTTLMonths'])
Success Response (201)
{
"success": true,
"status": 201,
"message": "Product created",
"data": {
"productId": "prd_01HXYZ1111ABCDEF0002",
"programId": "prg_01HXYZ9876ABCDEF0000",
"name": "Prepaid VISA Consumer 12m",
"scheme": "VISA",
"cardType": "CONSUMER",
"binCode": "SG-VISA-V-02",
"features": {
"has3DS": true,
"hasApplePay": true,
"hasGooglePay": true,
"hasJIT": false,
"hasSpendControl": false,
"hasMccControl": false
},
"controls": {
"isReloadable": false,
"isOneTimeUse": false,
"cardTTLMonths": 12,
"maxCardsPerCardholder": 5,
"spendingLimit": 1000,
"spendingPeriod": "TRANSAMOUNT"
},
"status": "ACTIVE",
"createdAt": "2026-05-26T11:00:00Z"
},
"meta": {
"requestId": "req_01HXY123456ABCDEF",
"platform": "Fyatu CaaS",
"timestamp": "2026-05-26T11:00:00Z"
}
}
Product Controls in Practice
Non-reloadable (controls.isReloadable: false)
Use this for prepaid, gift-card, or expense-allowance products where the cardholder receives a fixed balance at issuance and cannot add more funds. Any call to POST /cards/{id}/fund will be rejected with 422 CARD_NOT_RELOADABLE.
One-time use (controls.isOneTimeUse: true)
Cards are automatically terminated after their first settled transaction. Best for single-purchase virtual cards where you want strong controls on card reuse. The card remains ACTIVE until the first settlement clears.
TTL cap (controls.cardTTLMonths)
The card provider normally sets card expiry based on the scheme default (often 3–5 years). Setting cardTTLMonths caps that to a shorter window — for example, 12 ensures cards expire within one year of issuance even if the provider would have granted longer. Defaults to 36 months when not provided.
Per-cardholder card limit (controls.maxCardsPerCardholder)
Enforced at issuance time. The limit counts all non-TERMINATED cards under this product for the same cardholder. Issuing a card that would breach the limit returns 409 CARDHOLDER_CARD_LIMIT_EXCEEDED. Defaults to 5 when not provided.
Spending limit (controls.spendingLimit + controls.spendingPeriod)
Sets a maximum spend cap on every card issued under this product. spendingLimit is expressed in the program currency (USD). spendingPeriod sets the window:
| Period | Description |
|---|---|
TRANSAMOUNT | Cap applied per individual transaction |
DAILY | Cap resets at midnight UTC each day |
WEEKLY | Cap resets each Monday at midnight UTC |
MONTHLY | Cap resets on the 1st of each month at midnight UTC |
1000 / TRANSAMOUNT when not provided.
Error Codes
| Code | HTTP | Cause |
|---|---|---|
MISSING_FIELD | 400 | name not provided, or scheme omitted without a binCode |
INVALID_REQUEST | 400 | Request body is not valid JSON |
SCHEME_NOT_ALLOWED | 400 | The requested scheme is not enabled for your program |
BIN_NOT_FOUND | 404 | No BIN matches the supplied binCode |
BIN_NOT_ISSUABLE | 409 | The BIN exists but is not currently available for issuing |
BIN_MISMATCH | 400 | The BIN contradicts the requested scheme or cardType |
FEATURE_NOT_SUPPORTED_BY_BIN | 400 | A requested feature is not carried by the BIN — the message names which one |
FEATURE_NOT_ALLOWED | 400 | A requested feature flag is not available under your program catalog |
PROGRAM_NOT_FOUND | 404 | Program does not exist or belongs to another business |
INVALID_STATUS | 409 | Program is closed or not in a state that allows new products |
INSUFFICIENT_SCOPE | 403 | Key lacks accounts:write scope |
INTERNAL_ERROR | 500 | Server error |
Authorizations
API key from the FYATU CaaS portal. Pass as Authorization: Bearer <key>.
Path Parameters
Program ID (prefix prg_)
Body
application/json
Human-readable product name
Example:
"Prepaid VISA Consumer 12m"
Card network. Must match a scheme enabled on your program. Required only when binCode is omitted — a BIN already determines the scheme.
Available options:
VISA, MASTERCARD Example:
"VISA"
Issue this product against a specific BIN, which fixes the issuing country, scheme and supported wallets. Omit to create from scheme alone.
Available options:
US-VISA-V-01, US-MC-V-02, SG-VISA-V-01, SG-VISA-V-02, HK-VISA-V-01, HK-MC-V-01 Example:
"SG-VISA-V-01"
Available options:
CONSUMER, CORPORATE Example:
"CONSUMER"
Feature flags validated against your program catalog.
Show child attributes
Show child attributes
Card lifecycle and spend controls.
Show child attributes
Show child attributes

