Attach a credit card to a donor on the active gateway
Sends raw card details (or a tokenized payment_method) through Donation::createCustomer to register the card with the client’s active payment gateway and store the resulting reference on the donor. Refreshes the donor cache on success. Note: returns HTTP 200 even on gateway failure (failure message is returned in the body); caller must inspect the message text. Validation: donor_id required. Requires permission: donations_manage.
curl --request POST \
--url https://api.gratona.com/v1/admin/add_cc \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"donor_id": 12345,
"firstName": "Jane",
"lastName": "Doe",
"number": "4242424242424242",
"cvv": "123",
"expiryMonth": "12",
"expiryYear": "2027",
"payment_method": "pm_1J4XYZabcdef"
}
'import requests
url = "https://api.gratona.com/v1/admin/add_cc"
payload = {
"donor_id": 12345,
"firstName": "Jane",
"lastName": "Doe",
"number": "4242424242424242",
"cvv": "123",
"expiryMonth": "12",
"expiryYear": "2027",
"payment_method": "pm_1J4XYZabcdef"
}
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({
donor_id: 12345,
firstName: 'Jane',
lastName: 'Doe',
number: '4242424242424242',
cvv: '123',
expiryMonth: '12',
expiryYear: '2027',
payment_method: 'pm_1J4XYZabcdef'
})
};
fetch('https://api.gratona.com/v1/admin/add_cc', 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.gratona.com/v1/admin/add_cc",
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([
'donor_id' => 12345,
'firstName' => 'Jane',
'lastName' => 'Doe',
'number' => '4242424242424242',
'cvv' => '123',
'expiryMonth' => '12',
'expiryYear' => '2027',
'payment_method' => 'pm_1J4XYZabcdef'
]),
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.gratona.com/v1/admin/add_cc"
payload := strings.NewReader("{\n \"donor_id\": 12345,\n \"firstName\": \"Jane\",\n \"lastName\": \"Doe\",\n \"number\": \"4242424242424242\",\n \"cvv\": \"123\",\n \"expiryMonth\": \"12\",\n \"expiryYear\": \"2027\",\n \"payment_method\": \"pm_1J4XYZabcdef\"\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.gratona.com/v1/admin/add_cc")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"donor_id\": 12345,\n \"firstName\": \"Jane\",\n \"lastName\": \"Doe\",\n \"number\": \"4242424242424242\",\n \"cvv\": \"123\",\n \"expiryMonth\": \"12\",\n \"expiryYear\": \"2027\",\n \"payment_method\": \"pm_1J4XYZabcdef\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.gratona.com/v1/admin/add_cc")
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 \"donor_id\": 12345,\n \"firstName\": \"Jane\",\n \"lastName\": \"Doe\",\n \"number\": \"4242424242424242\",\n \"cvv\": \"123\",\n \"expiryMonth\": \"12\",\n \"expiryYear\": \"2027\",\n \"payment_method\": \"pm_1J4XYZabcdef\"\n}"
response = http.request(request)
puts response.read_body{
"message": "Credit card added successfully."
}{
"message": "Unauthorized",
"status": "error"
}{
"errors": {},
"status": "error",
"message": "The given data was invalid."
}Authorizations
Passport bearer token authentication for legacy admin sessions.
Body
Donor that will own the card.
12345
Cardholder first name.
"Jane"
Cardholder last name.
"Doe"
Raw PAN (when not using payment_method).
"4242424242424242"
Card verification value.
"123"
Two-digit expiry month.
"12"
Four-digit expiry year.
"2027"
Stripe PaymentMethod id (when present, raw card fields are ignored downstream).
"pm_1J4XYZabcdef"
Response
Either success or gateway-failure response — disambiguate via the message text.
"Credit card added successfully."
curl --request POST \
--url https://api.gratona.com/v1/admin/add_cc \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"donor_id": 12345,
"firstName": "Jane",
"lastName": "Doe",
"number": "4242424242424242",
"cvv": "123",
"expiryMonth": "12",
"expiryYear": "2027",
"payment_method": "pm_1J4XYZabcdef"
}
'import requests
url = "https://api.gratona.com/v1/admin/add_cc"
payload = {
"donor_id": 12345,
"firstName": "Jane",
"lastName": "Doe",
"number": "4242424242424242",
"cvv": "123",
"expiryMonth": "12",
"expiryYear": "2027",
"payment_method": "pm_1J4XYZabcdef"
}
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({
donor_id: 12345,
firstName: 'Jane',
lastName: 'Doe',
number: '4242424242424242',
cvv: '123',
expiryMonth: '12',
expiryYear: '2027',
payment_method: 'pm_1J4XYZabcdef'
})
};
fetch('https://api.gratona.com/v1/admin/add_cc', 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.gratona.com/v1/admin/add_cc",
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([
'donor_id' => 12345,
'firstName' => 'Jane',
'lastName' => 'Doe',
'number' => '4242424242424242',
'cvv' => '123',
'expiryMonth' => '12',
'expiryYear' => '2027',
'payment_method' => 'pm_1J4XYZabcdef'
]),
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.gratona.com/v1/admin/add_cc"
payload := strings.NewReader("{\n \"donor_id\": 12345,\n \"firstName\": \"Jane\",\n \"lastName\": \"Doe\",\n \"number\": \"4242424242424242\",\n \"cvv\": \"123\",\n \"expiryMonth\": \"12\",\n \"expiryYear\": \"2027\",\n \"payment_method\": \"pm_1J4XYZabcdef\"\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.gratona.com/v1/admin/add_cc")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"donor_id\": 12345,\n \"firstName\": \"Jane\",\n \"lastName\": \"Doe\",\n \"number\": \"4242424242424242\",\n \"cvv\": \"123\",\n \"expiryMonth\": \"12\",\n \"expiryYear\": \"2027\",\n \"payment_method\": \"pm_1J4XYZabcdef\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.gratona.com/v1/admin/add_cc")
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 \"donor_id\": 12345,\n \"firstName\": \"Jane\",\n \"lastName\": \"Doe\",\n \"number\": \"4242424242424242\",\n \"cvv\": \"123\",\n \"expiryMonth\": \"12\",\n \"expiryYear\": \"2027\",\n \"payment_method\": \"pm_1J4XYZabcdef\"\n}"
response = http.request(request)
puts response.read_body{
"message": "Credit card added successfully."
}{
"message": "Unauthorized",
"status": "error"
}{
"errors": {},
"status": "error",
"message": "The given data was invalid."
}