Card
Card collections let you accept payments from customers using their credit or debit cards. There are two ways to do this:
- One-time charge: Gravv generates a payment link for a single payment. Redirect the customer to the link, and Gravv handles the checkout page.
- Recurring charge: Gravv generates a payment link for the first payment. After the customer pays, Gravv sends a webhook event containing a card token. Use that token to charge the customer again without them re-entering their card details.
One-time charge
Initiate a collection request with the payment method set to card. Gravv returns a payment_link in the response. Redirect your customer to this link to complete the payment:
curl --request POST \
--url https://api.gravv.xyz/v1/collections \
--header 'Api-Key: <Api Key>' \
--header 'Idempotency-Key: order_789_attempt_1' \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--data '
{
"amount": "50",
"currency": "USD",
"country": "NG",
"customer_id": "04dfb2e5-1274-4214-b5fd-3415fde7dc17",
"client_customer_id": "checkers_user",
"client_reference": "9d8184a1-4a19-b74d-4797-9896aed01332",
"source": {
"source_type": "external",
"methods": [
"card"
]
},
"destination": {
"id": "bccb74d8-9715-478d-bcac-9d8184a19530",
"destination_type": "internal_crypto_wallet"
}
}
'
You will receive a response similar to this:
{
"data": {
"amount": "50",
"client_reference": "9d8184a1-4a19-b74d-4797-9896aed01332",
"country": "NG",
"currency": "USD",
"onramp_status": "initialized",
"payment_link": "https://pay-staging.gravv.xyz?transaction_id=07b655cc-3dbd-4f6c-a16c-4657946d2e08",
"transaction_id": "07b655cc-3dbd-4f6c-a16c-4657946d2e08",
"transaction_status": "pending"
},
"error": null
}
Redirect the customer to payment_link. They enter their card details on Gravv's checkout page and complete the payment there.
Recurring charge
The recurring charge flow uses the payment intent endpoints. Your backend creates a payment intent and receives a payment_link. Redirect the customer to that link to complete the first payment. After the customer pays, Gravv sends a webhook event to your configured endpoint containing a card_token. Store that token against the customer record to use for future charges.
Create a payment intent
Call the Create payment intent endpoint from your backend:
curl --request POST \
--url https://api.gravv.xyz/v1/collections/cards/payment-intents \
--header 'Api-Key: <Api Key>' \
--header 'Idempotency-Key: order_123_attempt_1' \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--data '
{
"customer_id": "f827e428-c497-4b21-8855-99d978909c28",
"client_customer_id": "merchant-user-123",
"amount": "3.50",
"currency": "USD",
"client_reference": "order-abc-123",
"destination": {
"destination_type": "internal_crypto_wallet",
"id": "b628ff35-429b-48f7-bcf0-6a49df106fc6"
},
"source": {
"type": "external",
"methods": ["card"]
}
}
'
You will receive a payment_link in the response. Redirect the customer to this link to complete payment:
{
"intent_id": "pi_429f578b-675a-4b68-abe3-856cd976257f",
"client_reference": "order-abc-123",
"status": "created",
"amount": "3.50",
"currency": "USD",
"requires_action": false,
"payment_link": "https://your-hosted-ui.com/pi_429f578b-...?session=eyJqd3Q...",
"created_at": "2026-04-08T10:00:00Z",
"expires_at": "2026-04-09T10:00:00Z"
}
After the customer completes payment, Gravv sends a webhook event to your configured endpoint. The payload contains a card_token you can use for future charges.
Charge a saved card
To charge the customer without redirecting them again, create a new payment intent and call the Charge card endpoint with the saved card_token and the new payment_intent_id. Billing fields are optional — any field you omit falls back to the customer record on file:
curl --request POST \
--url https://api.gravv.xyz/v1/collections/cards/charge \
--header 'Api-Key: <Api Key>' \
--header 'Idempotency-Key: order_456_attempt_1' \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--data '
{
"payment_intent_id": "pi_429f578b-675a-4b68-abe3-856cd976257f",
"card_token": "tokn_80aebb6ea2594a74bc215a64",
"first_name": "Jane",
"last_name": "Doe",
"email": "jane@example.com",
"billing_address1": "123 Market St",
"billing_city": "San Francisco",
"billing_state": "CA",
"billing_zip": "94105",
"billing_country": "US"
}
'
A successful charge returns:
{
"payment_intent_id": "pi_429f578b-...",
"transaction_id": "txn_a1b2c3d4-...",
"status": "succeeded",
"requires_action": false
}
You can also trigger a recurring charge without a separate call to the Charge card endpoint. Pass the card_token in the card_token field when you call Create payment intent. Gravv charges the card immediately and returns the result in the response.
Manage saved cards
Gravv stores card tokens against a customer record. Use the endpoints below to retrieve or remove them.
Get saved cards
Call the Get saved cards endpoint to list all active cards. Pass customer_id as a query parameter to filter by customer:
curl --request GET \
--url 'https://api.gravv.xyz/v1/collections/cards?customer_id=f827e428-c497-4b21-8855-99d978909c28' \
--header 'Api-Key: <Api Key>'
Get saved card
Call the Get saved card endpoint to retrieve a single card by ID:
curl --request GET \
--url https://api.gravv.xyz/v1/collections/cards/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
--header 'Api-Key: <Api Key>'
You will receive a response similar to this:
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"card_token": "tokn_80aebb6ea2594a74bc215a64",
"card_last4": "1111",
"card_brand": "visa",
"card_exp_month": "12",
"card_exp_year": "2028",
"is_default": true,
"is_expired": false,
"is_expiring_soon": false,
"created_at": "2026-04-08T10:00:00Z"
}
The computed fields on a saved card are:
| Field | Description |
|---|---|
is_expired |
The card token has aged past its expiration window |
is_expiring_soon |
The card expires within 30 days |
Delete a saved card
Call the Delete saved card endpoint to remove a saved card. This operation is idempotent. It returns success even if the card does not exist:
curl --request DELETE \
--url https://api.gravv.xyz/v1/collections/cards/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
--header 'Api-Key: <Api Key>'
You'll get a response similar to the following:
{
"success": true,
"message": "card deleted successfully"
}