Withdraw from a card
curl --request POST \
--url https://api.kemycard.com/v1/cards/{code}/withdraw \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"amount": 20
}'import requests
url = "https://api.kemycard.com/v1/cards/{code}/withdraw"
payload = { "amount": 20 }
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({amount: 20})
};
fetch('https://api.kemycard.com/v1/cards/{code}/withdraw', 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.kemycard.com/v1/cards/{code}/withdraw",
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([
'amount' => 20
]),
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.kemycard.com/v1/cards/{code}/withdraw"
payload := strings.NewReader("{\n \"amount\": 20\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.kemycard.com/v1/cards/{code}/withdraw")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"amount\": 20\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.kemycard.com/v1/cards/{code}/withdraw")
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 \"amount\": 20\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"card_code": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"withdrawal_id": "ctx_9f2c1e0b7a6d5c4b3a291807",
"status": "completed",
"amount": 20,
"fee": 1.2,
"net_amount": 18.8,
"credited_balance": "cards_visa",
"card_balance": 30,
"currency": "USD"
}
}{
"success": false,
"error": {
"code": "INSUFFICIENT_BALANCE",
"message": "Insufficient ops balance.",
"details": {
"required": 50,
"available": 10,
"balance_type": "cards_mastercard"
}
}
}{
"success": false,
"error": {
"code": "ACCOUNT_SUSPENDED_NEGATIVE_BALANCE",
"message": "Your account is suspended because one of your ops balances is negative. Top up the negative balance to restore access. Read-only requests (GET) remain available.",
"details": {
"negative_balance_since": "2026-10-15T08:00:00+00:00"
}
}
}{
"success": false,
"error": {
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found.",
"details": null
}
}{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Missing required fields.",
"details": {}
},
"meta": {
"request_id": "a4f8e2c1b3d97056",
"mode": "test",
"timestamp": "2023-11-07T05:31:56Z"
}
}Cards
Withdraw from a Card
Withdraws part of the balance of an active card back to your cards_visa or cards_mastercard balance
(depending on the card brand). The withdrawal is synchronous.
- Minimum: 5 USD per withdrawal.
- Balance left on the card: at least 5 USD must remain on the card after the withdrawal. The maximum you can
withdraw is therefore the card balance minus 5 USD (a card with 30 USD allows a withdrawal of up to 25 USD,
and a card with less than 10 USD cannot be withdrawn from). To recover the whole balance, terminate the card
(
POST /cards/{code}/terminate). - Card balance: read in real time from the card provider before the withdrawal.
- Fees: the card withdrawal fee of your plan (see Plans) is deducted from the
amount withdrawn; your balance is credited with
net_amount.
Sends a card.withdrawal.completed webhook.
POST
/
cards
/
{code}
/
withdraw
Withdraw from a card
curl --request POST \
--url https://api.kemycard.com/v1/cards/{code}/withdraw \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"amount": 20
}'import requests
url = "https://api.kemycard.com/v1/cards/{code}/withdraw"
payload = { "amount": 20 }
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({amount: 20})
};
fetch('https://api.kemycard.com/v1/cards/{code}/withdraw', 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.kemycard.com/v1/cards/{code}/withdraw",
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([
'amount' => 20
]),
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.kemycard.com/v1/cards/{code}/withdraw"
payload := strings.NewReader("{\n \"amount\": 20\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.kemycard.com/v1/cards/{code}/withdraw")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"amount\": 20\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.kemycard.com/v1/cards/{code}/withdraw")
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 \"amount\": 20\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"card_code": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"withdrawal_id": "ctx_9f2c1e0b7a6d5c4b3a291807",
"status": "completed",
"amount": 20,
"fee": 1.2,
"net_amount": 18.8,
"credited_balance": "cards_visa",
"card_balance": 30,
"currency": "USD"
}
}{
"success": false,
"error": {
"code": "INSUFFICIENT_BALANCE",
"message": "Insufficient ops balance.",
"details": {
"required": 50,
"available": 10,
"balance_type": "cards_mastercard"
}
}
}{
"success": false,
"error": {
"code": "ACCOUNT_SUSPENDED_NEGATIVE_BALANCE",
"message": "Your account is suspended because one of your ops balances is negative. Top up the negative balance to restore access. Read-only requests (GET) remain available.",
"details": {
"negative_balance_since": "2026-10-15T08:00:00+00:00"
}
}
}{
"success": false,
"error": {
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found.",
"details": null
}
}{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Missing required fields.",
"details": {}
},
"meta": {
"request_id": "a4f8e2c1b3d97056",
"mode": "test",
"timestamp": "2023-11-07T05:31:56Z"
}
}Authorizations
API key (sk_test_... or sk_live_...)
Path Parameters
Code of the card: the code returned when the card is created (POST /cards).
Body
application/json
Amount to withdraw from the card (USD, minimum 5; at least 5 USD must remain on the card)
Required range:
x >= 5Example:
20