Skip to content

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"
}