Ginger Payments
Recurring payments

Recurring payments

Charge a stored card for subscriptions and other repeated payments, without your customer being present.

Use recurring payments for subscriptions, instalments and other repeated charges. They cover two kinds of series:

schedule_typeUse it forExample
scheduledCharges at fixed intervalsA monthly subscription
unscheduledCharges at moments that varyAutomatic top-ups when a balance runs low

Recurring payments work in two stages:

  1. First transaction. Your customer pays, or verifies their card, and authenticates. Ginger Payments stores the card in the vault and returns a vault_token.
  2. Subsequent transactions. You charge the stored card whenever a payment is due. Your customer isn't present and doesn't need to do anything.

Keep these rules in mind:

  • A recurring series is valid for at most one year. After that, start a new series with a new first transaction.
  • The amount of the first transaction can differ from the subsequent ones.
  • For a payment that your customer starts themselves, such as a faster checkout, use one-click payments instead.

Apple Pay and Google Pay support recurring payments as well, with a few differences. See Recurring payments with Apple Pay and Recurring payments with Google Pay.

Step 1: Create the first transaction

Create an order with a credit-card transaction and set these fields in payment_method_details:

FieldValue
recurring_typefirst
schedule_typescheduled or unscheduled

How your customer completes the payment depends on your integration.

Create the order and redirect your customer to the payment_url of the transaction in the response. Your customer enters their card details and authenticates on the hosted payment page.

curl https://api.dev.gingerpayments.com/v1/orders/ \
  --user "$API_KEY:" \
  --header "Content-Type: application/json" \
  --data '{
    "merchant_order_id": "SUB-001",
    "amount": 1000,
    "currency": "EUR",
    "description": "Subscription setup",
    "return_url": "https://www.example.com/return",
    "transactions": [
      {
        "payment_method": "credit-card",
        "payment_method_details": {
          "recurring_type": "first",
          "schedule_type": "scheduled"
        }
      }
    ],
    "customer": {
      "merchant_customer_id": "CUST-ABCDE",
      "email_address": "jane.doe@example.com",
      "first_name": "Jane",
      "last_name": "Doe",
      "address_type": "billing",
      "address": "123 Abbey Road",
      "postal_code": "NW8 9AY",
      "country": "GB",
      "city": "London",
      "ip_address": "203.0.113.10"
    }
  }'

Verify a card without charging it

To only store and verify the card, set amount to 0 in the first transaction. Your customer still authenticates, but isn't charged.

Step 2: Store the vault token

When the order is completed, retrieve it to get the vault_token:

curl https://api.dev.gingerpayments.com/v1/orders/5d2a9c84-1f6b-4e37-9a0d-7c3e8b1f2a96/ \
  --user "$API_KEY:"

The token is in the payment_method_details of the transaction. The response is shortened:

{
  "id": "5d2a9c84-1f6b-4e37-9a0d-7c3e8b1f2a96",
  "status": "completed",
  "transactions": [
    {
      "id": "a41f7e2c-8b3d-4c95-9e60-1d7b2f8c3a04",
      "payment_method": "credit-card",
      "payment_method_details": {
        "card_expiry": "122029",
        "cardholder_name": "Jane Doe",
        "recurring_type": "first",
        "schedule_type": "scheduled",
        "truncated_pan": "************4444",
        "vault_token": "0c8fd8ab-25ec-4109-ac8f-495804aa5026"
      },
      "status": "completed"
    }
  ]
}

Store the vault_token and the transaction id securely, and link them to your customer's subscription. You need one of them for every subsequent charge.

Step 3: Charge subsequent payments

When a payment is due, create an order with recurring_type set to recurring. Reference the series with the first_transaction_id, the id of the transaction from step 1:

curl https://api.dev.gingerpayments.com/v1/orders/ \
  --user "$API_KEY:" \
  --header "Content-Type: application/json" \
  --data '{
    "merchant_order_id": "SUB-001-CYCLE-02",
    "amount": 4000,
    "currency": "EUR",
    "description": "Monthly subscription",
    "webhook_url": "https://www.example.com/webhook",
    "transactions": [
      {
        "payment_method": "credit-card",
        "payment_method_details": {
          "recurring_type": "recurring",
          "first_transaction_id": "a41f7e2c-8b3d-4c95-9e60-1d7b2f8c3a04"
        }
      }
    ],
    "customer": {
      "merchant_customer_id": "CUST-ABCDE",
      "ip_address": "203.0.113.10"
    }
  }'

Instead of the first_transaction_id, you can send the vault_token from step 2.

The payment is processed without your customer. There's no payment_url to redirect to. Follow the result with a webhook and a status request.

Continue a series from another platform

Did the first transaction of a series run on another payment platform? You can continue the series with Ginger Payments, without asking your customer to authenticate again. This is only possible with a server-to-server integration.

You need the first_network_transaction_id: the identifier the card network assigned to the first authorization of the series. Ask your previous payment provider for it.

Create the order

Create an order with recurring_type set to recurring and the first_network_transaction_id:

curl https://api.dev.gingerpayments.com/v1/orders/ \
  --user "$API_KEY:" \
  --header "Content-Type: application/json" \
  --data '{
    "merchant_order_id": "MIGRATED-SUB-001",
    "amount": 4000,
    "currency": "EUR",
    "description": "Monthly subscription",
    "transactions": [
      {
        "payment_method": "credit-card",
        "payment_method_details": {
          "recurring_type": "recurring",
          "first_network_transaction_id": "MDSIZQ7RH0128"
        }
      }
    ]
  }'

The transaction in the response contains a setup_token in its payment_method_details. Save it, together with the order id and transaction id.

Store the card in the vault

Send the card details and the setup_token to the vault. The setup token can be used once, within 300 seconds:

curl https://tokens.dev.gingerpayments.com/v1/cards/ \
  --user "$API_KEY:" \
  --header "Content-Type: application/json" \
  --data '{
    "name": "John Doe",
    "pan": "4111111111111111",
    "expiry": "012030",
    "setup_token": "5d04ff5e-eb9d-42c8-8bcd-8a29f49ccf58"
  }'

The response contains a vault_token that refers to the stored card.

Start the payment

Assign the vault_token to the transaction to process the payment:

curl https://api.dev.gingerpayments.com/v1/orders/0a73c8e3-7a2f-40ee-8f6c-fa41a37c140a/transactions/7e5d1b90-2c4a-4f83-b6d1-9a0e3c5f8b27/initiate/ \
  --user "$API_KEY:" \
  --header "Content-Type: application/json" \
  --data '{
    "vault_token": "ab39817c-7e19-497a-ac7b-23526473b3c1"
  }'

The response contains the order and its transaction. It's shortened here:

{
  "id": "0a73c8e3-7a2f-40ee-8f6c-fa41a37c140a",
  "amount": 4000,
  "currency": "EUR",
  "merchant_order_id": "MIGRATED-SUB-001",
  "status": "processing",
  "transactions": [
    {
      "id": "7e5d1b90-2c4a-4f83-b6d1-9a0e3c5f8b27",
      "amount": 4000,
      "payment_method": "credit-card",
      "payment_method_brand": "visa",
      "payment_method_details": {
        "approval_code": "08C405",
        "authorization_iso_response_code": "00",
        "first_network_transaction_id": "MDSIZQ7RH0128",
        "network_transaction_id": "MDSIRCRRH0128",
        "recurring_type": "recurring",
        "schedule_type": "unscheduled",
        "vault_token": "ab39817c-7e19-497a-ac7b-23526473b3c1"
      },
      "status": "accepted"
    }
  ]
}

Store the vault_token. For the next charges in the series, skip the vault step: create the order and start the payment with the stored vault_token.

Visa Account Name Inquiry

Visa Account Name Inquiry (ANI) checks whether the cardholder name your customer enters matches the name the issuer has on file. It runs automatically when all of these apply to the first transaction:

  • The amount is 0.
  • Your customer pays with a Visa card.
  • Your customer enters the cardholder name.

The result is in the payment_method_details of the transaction:

{
  "ani_results": {
    "status": "00",
    "status_description": "ANI successfully performed",
    "match": "01",
    "match_description": "full match"
  }
}
statusMeaning
00ANI was performed.
01ANI was requested but not performed.
02ANI was requested but the issuer doesn't support it.
matchMeaning
01Full match
50Partial match
99No match

On this page