curl --request POST \
--url https://api-sandbox.endl.io/api/v0/customer/{businessId}/card-users/{cardholderId}/cards/scoped \
--header 'Api-Key: <api-key>' \
--header 'Api-Version: <api-version>' \
--header 'Content-Type: application/json' \
--data '
{
"amountInUSDCents": 4299,
"bufferPercentage": 10,
"expiresAt": "2026-10-01T00:00:00Z",
"allowedMccs": [
"5411"
],
"allowedMerchants": [
"Amazon"
],
"displayName": "Agent card",
"purpose": "order 8841"
}
'import requests
url = "https://api-sandbox.endl.io/api/v0/customer/{businessId}/card-users/{cardholderId}/cards/scoped"
payload = {
"amountInUSDCents": 4299,
"bufferPercentage": 10,
"expiresAt": "2026-10-01T00:00:00Z",
"allowedMccs": ["5411"],
"allowedMerchants": ["Amazon"],
"displayName": "Agent card",
"purpose": "order 8841"
}
headers = {
"Api-Version": "<api-version>",
"Api-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'Api-Version': '<api-version>',
'Api-Key': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
amountInUSDCents: 4299,
bufferPercentage: 10,
expiresAt: '2026-10-01T00:00:00Z',
allowedMccs: ['5411'],
allowedMerchants: ['Amazon'],
displayName: 'Agent card',
purpose: 'order 8841'
})
};
fetch('https://api-sandbox.endl.io/api/v0/customer/{businessId}/card-users/{cardholderId}/cards/scoped', 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-sandbox.endl.io/api/v0/customer/{businessId}/card-users/{cardholderId}/cards/scoped",
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([
'amountInUSDCents' => 4299,
'bufferPercentage' => 10,
'expiresAt' => '2026-10-01T00:00:00Z',
'allowedMccs' => [
'5411'
],
'allowedMerchants' => [
'Amazon'
],
'displayName' => 'Agent card',
'purpose' => 'order 8841'
]),
CURLOPT_HTTPHEADER => [
"Api-Key: <api-key>",
"Api-Version: <api-version>",
"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-sandbox.endl.io/api/v0/customer/{businessId}/card-users/{cardholderId}/cards/scoped"
payload := strings.NewReader("{\n \"amountInUSDCents\": 4299,\n \"bufferPercentage\": 10,\n \"expiresAt\": \"2026-10-01T00:00:00Z\",\n \"allowedMccs\": [\n \"5411\"\n ],\n \"allowedMerchants\": [\n \"Amazon\"\n ],\n \"displayName\": \"Agent card\",\n \"purpose\": \"order 8841\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Api-Version", "<api-version>")
req.Header.Add("Api-Key", "<api-key>")
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-sandbox.endl.io/api/v0/customer/{businessId}/card-users/{cardholderId}/cards/scoped")
.header("Api-Version", "<api-version>")
.header("Api-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"amountInUSDCents\": 4299,\n \"bufferPercentage\": 10,\n \"expiresAt\": \"2026-10-01T00:00:00Z\",\n \"allowedMccs\": [\n \"5411\"\n ],\n \"allowedMerchants\": [\n \"Amazon\"\n ],\n \"displayName\": \"Agent card\",\n \"purpose\": \"order 8841\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-sandbox.endl.io/api/v0/customer/{businessId}/card-users/{cardholderId}/cards/scoped")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Api-Version"] = '<api-version>'
request["Api-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"amountInUSDCents\": 4299,\n \"bufferPercentage\": 10,\n \"expiresAt\": \"2026-10-01T00:00:00Z\",\n \"allowedMccs\": [\n \"5411\"\n ],\n \"allowedMerchants\": [\n \"Amazon\"\n ],\n \"displayName\": \"Agent card\",\n \"purpose\": \"order 8841\"\n}"
response = http.request(request)
puts response.read_body{
"cardId": "6eab027d-1c2e-4f0a-9b1d-3c5e7a9f0b12",
"cardholderId": "cus_6OzDYZWl5Aim37RwvZfZ",
"status": "active",
"last4": "2464",
"expiryMonth": "12",
"expiryYear": "2030",
"scope": {
"amountInUSDCents": 4299,
"lifetimeLimitCents": 4729,
"bufferPercentage": 10,
"expiresAt": "2026-10-01T00:00:00Z",
"allowedMccs": [
"5411"
],
"allowedMerchants": [
"Amazon"
],
"cardType": "consumer",
"purpose": "order 8841",
"spentAt": null
},
"encryptedCard": {
"alg": "RSA-OAEP-256+A256GCM",
"keyId": "my-card-key",
"encryptedKey": "kD3n…==",
"iv": "nV7kuhxhBtvq9s1Z",
"ciphertext": "5u7fkhvc9cKI…",
"tag": "XuMrbHy9vx3oQ2cR1ZpA8w==",
"aad": "6eab027d-1c2e-4f0a-9b1d-3c5e7a9f0b12"
}
}{
"code": 400,
"message": "amountInUSDCents must be an integer from 1 to 10000000",
"status": "ERROR",
"data": null,
"errors": [
{
"code": "ERRCRD_1005",
"message": "amountInUSDCents must be an integer from 1 to 10000000",
"field": null
}
]
}{
"code": 401,
"message": "Partner API key required",
"status": "ERROR",
"data": null,
"errors": [
{
"code": "ERRCORE_1004",
"message": "Partner API key required",
"field": null
}
]
}{
"code": 403,
"message": "Card issuing not available",
"status": "ERROR",
"data": null,
"errors": [
{
"code": "ERRCRD_1007",
"message": "Card issuing not available",
"field": null
}
]
}{
"code": 404,
"message": "Cardholder not found",
"status": "ERROR",
"data": null,
"errors": [
{
"code": "ERRCRD_1002",
"message": "Cardholder not found",
"field": null
}
]
}{
"code": 409,
"message": "Card already issued",
"status": "ERROR",
"data": null,
"errors": [
{
"code": "ERRCRD_1008",
"message": "Card already issued",
"field": null
}
]
}{
"code": 502,
"message": "Card issuing temporarily unavailable",
"status": "ERROR",
"data": null,
"errors": [
{
"code": "ERRCRD_1009",
"message": "Card issuing temporarily unavailable",
"field": null
}
]
}Issue single-use card
Issues a scoped, single-use virtual card to an active cardholder.
Card details come back once, in encryptedCard, and there is no endpoint to fetch them again. A retry with the same Idempotency-Key returns 409 ERRCRD_1008 with no details. Decrypt and use the card straight away — see Card details encryption.
The business needs a registered RSA public key before any card can be issued; without one this fails with 400 ERRCRD_1004.
lifetimeLimitCents comes back as the amount plus the buffer, rounded up.
curl --request POST \
--url https://api-sandbox.endl.io/api/v0/customer/{businessId}/card-users/{cardholderId}/cards/scoped \
--header 'Api-Key: <api-key>' \
--header 'Api-Version: <api-version>' \
--header 'Content-Type: application/json' \
--data '
{
"amountInUSDCents": 4299,
"bufferPercentage": 10,
"expiresAt": "2026-10-01T00:00:00Z",
"allowedMccs": [
"5411"
],
"allowedMerchants": [
"Amazon"
],
"displayName": "Agent card",
"purpose": "order 8841"
}
'import requests
url = "https://api-sandbox.endl.io/api/v0/customer/{businessId}/card-users/{cardholderId}/cards/scoped"
payload = {
"amountInUSDCents": 4299,
"bufferPercentage": 10,
"expiresAt": "2026-10-01T00:00:00Z",
"allowedMccs": ["5411"],
"allowedMerchants": ["Amazon"],
"displayName": "Agent card",
"purpose": "order 8841"
}
headers = {
"Api-Version": "<api-version>",
"Api-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'Api-Version': '<api-version>',
'Api-Key': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
amountInUSDCents: 4299,
bufferPercentage: 10,
expiresAt: '2026-10-01T00:00:00Z',
allowedMccs: ['5411'],
allowedMerchants: ['Amazon'],
displayName: 'Agent card',
purpose: 'order 8841'
})
};
fetch('https://api-sandbox.endl.io/api/v0/customer/{businessId}/card-users/{cardholderId}/cards/scoped', 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-sandbox.endl.io/api/v0/customer/{businessId}/card-users/{cardholderId}/cards/scoped",
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([
'amountInUSDCents' => 4299,
'bufferPercentage' => 10,
'expiresAt' => '2026-10-01T00:00:00Z',
'allowedMccs' => [
'5411'
],
'allowedMerchants' => [
'Amazon'
],
'displayName' => 'Agent card',
'purpose' => 'order 8841'
]),
CURLOPT_HTTPHEADER => [
"Api-Key: <api-key>",
"Api-Version: <api-version>",
"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-sandbox.endl.io/api/v0/customer/{businessId}/card-users/{cardholderId}/cards/scoped"
payload := strings.NewReader("{\n \"amountInUSDCents\": 4299,\n \"bufferPercentage\": 10,\n \"expiresAt\": \"2026-10-01T00:00:00Z\",\n \"allowedMccs\": [\n \"5411\"\n ],\n \"allowedMerchants\": [\n \"Amazon\"\n ],\n \"displayName\": \"Agent card\",\n \"purpose\": \"order 8841\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Api-Version", "<api-version>")
req.Header.Add("Api-Key", "<api-key>")
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-sandbox.endl.io/api/v0/customer/{businessId}/card-users/{cardholderId}/cards/scoped")
.header("Api-Version", "<api-version>")
.header("Api-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"amountInUSDCents\": 4299,\n \"bufferPercentage\": 10,\n \"expiresAt\": \"2026-10-01T00:00:00Z\",\n \"allowedMccs\": [\n \"5411\"\n ],\n \"allowedMerchants\": [\n \"Amazon\"\n ],\n \"displayName\": \"Agent card\",\n \"purpose\": \"order 8841\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-sandbox.endl.io/api/v0/customer/{businessId}/card-users/{cardholderId}/cards/scoped")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Api-Version"] = '<api-version>'
request["Api-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"amountInUSDCents\": 4299,\n \"bufferPercentage\": 10,\n \"expiresAt\": \"2026-10-01T00:00:00Z\",\n \"allowedMccs\": [\n \"5411\"\n ],\n \"allowedMerchants\": [\n \"Amazon\"\n ],\n \"displayName\": \"Agent card\",\n \"purpose\": \"order 8841\"\n}"
response = http.request(request)
puts response.read_body{
"cardId": "6eab027d-1c2e-4f0a-9b1d-3c5e7a9f0b12",
"cardholderId": "cus_6OzDYZWl5Aim37RwvZfZ",
"status": "active",
"last4": "2464",
"expiryMonth": "12",
"expiryYear": "2030",
"scope": {
"amountInUSDCents": 4299,
"lifetimeLimitCents": 4729,
"bufferPercentage": 10,
"expiresAt": "2026-10-01T00:00:00Z",
"allowedMccs": [
"5411"
],
"allowedMerchants": [
"Amazon"
],
"cardType": "consumer",
"purpose": "order 8841",
"spentAt": null
},
"encryptedCard": {
"alg": "RSA-OAEP-256+A256GCM",
"keyId": "my-card-key",
"encryptedKey": "kD3n…==",
"iv": "nV7kuhxhBtvq9s1Z",
"ciphertext": "5u7fkhvc9cKI…",
"tag": "XuMrbHy9vx3oQ2cR1ZpA8w==",
"aad": "6eab027d-1c2e-4f0a-9b1d-3c5e7a9f0b12"
}
}{
"code": 400,
"message": "amountInUSDCents must be an integer from 1 to 10000000",
"status": "ERROR",
"data": null,
"errors": [
{
"code": "ERRCRD_1005",
"message": "amountInUSDCents must be an integer from 1 to 10000000",
"field": null
}
]
}{
"code": 401,
"message": "Partner API key required",
"status": "ERROR",
"data": null,
"errors": [
{
"code": "ERRCORE_1004",
"message": "Partner API key required",
"field": null
}
]
}{
"code": 403,
"message": "Card issuing not available",
"status": "ERROR",
"data": null,
"errors": [
{
"code": "ERRCRD_1007",
"message": "Card issuing not available",
"field": null
}
]
}{
"code": 404,
"message": "Cardholder not found",
"status": "ERROR",
"data": null,
"errors": [
{
"code": "ERRCRD_1002",
"message": "Cardholder not found",
"field": null
}
]
}{
"code": 409,
"message": "Card already issued",
"status": "ERROR",
"data": null,
"errors": [
{
"code": "ERRCRD_1008",
"message": "Card already issued",
"field": null
}
]
}{
"code": 502,
"message": "Card issuing temporarily unavailable",
"status": "ERROR",
"data": null,
"errors": [
{
"code": "ERRCRD_1009",
"message": "Card issuing temporarily unavailable",
"field": null
}
]
}Authorizations
Partner API key. Must carry the cards permission.
Headers
The API version this request targets. 2026-09.1. See Versioning.
^\d{4}-\d{2}\.\d+$1–64 characters. A retry with the same key never creates a second card.
1 - 64Path Parameters
Your business customer, cus_…, enabled for cards.
An active cardholder of that business, cus_….
Body
1 – 10,000,000. Whole numbers only.
0 – 20. Defaults to 20.
ISO-8601 with offset. Must be in the future and no more than 365 days out.
Non-empty, unique 4-digit codes.
Non-empty, at most 25 unique names, 1–64 characters each.
At most 26 characters — letters, digits, spaces, . and -, with at least one letter.
At most 255 characters.
Response
The card, with its details encrypted in encryptedCard.
The card. Also encryptedCard.aad.
Echo of the path.
active.
Last four digits.
MM.
YYYY.
The spend scope as applied.
The card number, CVV and expiry — returned once, encrypted to your RSA public key.
Show child attributes
Show child attributes