Subscriptions (beta)

📘

This feature is in beta

Subscriptions are in beta. Please contact your Neon representative if you'd like to try them out.

📘

Limited APM coverage

For now, subscriptions can only be paid for via debit or credit card. In addition, subscriptions are currently unavailable in the following countries due to payment processor restrictions: Argentina, Brazil, Chile, Mexico, Peru. We expect to have these countries live in H2 2025.

📘

This is a standalone feature

Subscriptions are currently not integrated into the webshop, and require calling our API to create new subscriptions. If you have a webshop and would like to test subscriptions out, contact us.

A subscription is a purchase that entitles a user to a recurring benefit. Upon purchase, the user receives a benefit that lasts until the end of their billing period (e.g. one month), at which point they're charged again to maintain the benefit. This continues until the user cancels their subscription or their payment method is rejected.

Terminology

  • Subscription product: a product to which a user can subscribe.
  • Subscription: an object representing a single user's recurring purchase of a subscription product.
  • Invoice: an object representing a single billing cycle's payment for a subscription. Each invoice is attached to a subscription via subscriptionId.
  • Entitlement: the process of granting a user access to a subscription product.

Creating a subscription

You can create a subscription by calling the POST /subscription API endpoint with some basic information:

curl 'https://api.neonpay.com/subscription' \
  -X POST
  -H 'content-type: application/json' \
  -H $'x-api-key: {{your API key}}' \
  -d '{
  "sku": "test-sku",
  "name": "Medieval Gamer",
  "price": 1249,
  "imageUrl": "https://placedog.net/400/400",
  "currency": "USD",
  "frequency": "monthly",
  "accountId": "test-player-id",
  "returnUrl": "https://example.com/subscription",
  "locale": "en-US",
  "country": "US"
}'

200 OK
{
  "subscription": {
    "id": "SUB-06B4K3-MW11RC-V25A3K-MQT063G0",
    "sku": "test-sku",
    "name": "Medieval Gamer",
    "imageUrl": "https://placedog.net/400/400",
    "externalReferenceId": null,
    "status": "inactive",
    "price": 1249,
    "currency": "USD",
    "frequency": "monthly",
    "country": "US",
    "locale": "en-US",
    "accountId": "test-player-id",
    "accountDisplayName": null,
    "externalMetadata": {}
  }.
  "redirectUrl": "http://checkout.neonpay.com/en-US/subscription/SUB-06B4K3-MW11RC-V25A3K-MQT063G0"
}

You should then redirect the user to the redirect URL, where they can enter their payment credentials and complete their purchase.

Once the user completes the subscription flow (including any 3D Secure verification their bank requires), we'll redirect them to the returnUrl you passed in, with subscriptionId and subscriptionToken appended as query parameters. You can then call GET /subscriptions/{subscriptionId} to retrieve the subscription status and show the result to the user. If no returnUrl is provided, the result is displayed on Neon's hosted page and the user is not returned to your site.

curl "https://api.neonpay.com/subscriptions/SUB-06B4K3-MW11RC-V25A3K-MQT063G0"
  -H 'X-Api-Key: {{your API key}}'

200 OK
{
  "id": "SUB-06B4K3-MW11RC-V25A3K-MQT063G0",
  "sku": "test-sku",
  "name": "Medieval Gamer",
  "imageUrl": "https://placedog.net/400/400",
  "externalReferenceId": null,
  "status": "active",
  "price": 1249,
  "currency": "USD",
  "frequency": "monthly",
  "country": "US",
  "locale": "en-US",
  "accountId": "test-player-id",
  "accountDisplayName": null,
  "externalMetadata": {}
}

Fulfillment

Once the user completes their purchase, we'll send the subscription.activated webhook to your listener. This webhook is fired when the user initially signs up for a subscription. Listen for this webhook to know when to entitle a user to a subscription product.

Here's an example webhook:

{
  "id": "e7d38081-11ac-464d-8804-86875c8bc97e",
  "type": "subscription.activated",
  "version": 1,
  "isSandbox": true,
  "data": {
    "subscription": {
      "id": "SUB-06B4K3-MW11RC-V25A3K-MQT063G0",
      "sku": "test-sku",
      "name": "Medieval Gamer",
      "imageUrl": "https://placedog.net/400/400",
      "externalReferenceId": null,
      "status": "active",
      "price": 1249,
      "currency": "USD",
      "frequency": "monthly",
      "country": "US",
      "locale": "en-US",
      "accountId": "test-player-id",
      "accountDisplayName": null,
      "externalMetadata": {}
    }
  }
}

Upon receiving this webhook, you should entitle test-player-id to the test-sku subscription product.

Recurring payments

Neon handles all logic related to recurring billing for a subscription, so no action should be required on your part per billing cycle. (If your entitlement system requires re-entitling users each billing period, you will still need to handle that. However, you can safely assume that, once the subscription.activated webhook is sent, the subscription will remain active until we send a subscription.canceled webhook; see below for more on cancellation.)

You can optionally listen for the invoice.paid webhook. We send this each time an invoice is paid successfully, and it contains payment-specific information like your net proceeds and the settlement currency. However, you shouldn't generally need to action on it, beyond storing it for your records.

Here's an example webhook:

{
  "id": "85823699-1334-4d15-afe2-bc309fc311f1",
  "type": "invoice.paid",
  "version": 1,
  "data": {
    "invoice": {
      "id": "INV-06B4K3-P94DV3-HDAY4M-4MTWGNY8",
      "date": "2025-04-18T15:40:05.002Z",
      "totalAmount": 1360,
      "subtotalAmount": 1249,
      "taxAmount": 111,
      "currency": "USD",
      "subscriptionId": "SUB-06B4K3-MW11RC-V25A3K-MQT063G0",
      "fee": {
        "settlementCurrency": "USD",
        "fxRate": 1,
        "feeAmount": 119,
        "netProceedsAmount": 1130
      }
    }
  }
}

Payment failures

When the user initially signs up for a subscription, they're prompted to enter their payment details. At this point, if their payment fails to complete (for example, if they're declined), we'll prompt them to re-enter their payment details.

Afterwards, if we encounter an error when making a renewal payment, we'll retry the payment method for 24 hours. If the payment method continues to fail after 24 hours, we'll cancel the subscription.

Canceling subscriptions

If a user no longer wants to be billed for a subscription, you can call the POST /subscriptions/{subscriptionId}/cancel endpoint to cancel the subscription. Note that this doesn't immediately cancel the subscription; instead, the subscription is marked as pending_cancellation, and the user should continue to receive benefits until the end of the billing cycle. On the next billing cycle, the subscription will be canceled.

You can also use the Console to cancel a subscription. Additionally, in sandbox mode only, you can cancel a subscription immediately (as opposed to marking it for cancellation at the end of the current billing cycle).

When a subscription is actually canceled (as opposed to just being marked for cancellation), we'll send a subscription.canceled webhook. Upon receipt, you should remove the user's entitlement.

Here's an example webhook:

subscription.canceled
{
  "id": "290e9be9-5abe-45a5-8a18-43b091e9198c",
  "type": "subscription.canceled",
  "version": 1,
  "isSandbox": true,
  "data": {
    "subscription": {
      "id": "SUB-06B4K3-MW11RC-V25A3K-MQT063G0",
      "sku": "test-sku",
      "name": "Medieval Gamer",
      "imageUrl": "https://placedog.net/400/400",
      "externalReferenceId": null,
      "status": "canceled",
      "price": 1249,
      "currency": "USD",
      "frequency": "monthly",
      "country": "US",
      "locale": "en-US",
      "accountId": "test-player-id",
      "accountDisplayName": null,
      "externalMetadata": {}
    }
  }
}

Updating a payment method

To let a user update their subscription's payment method, call POST /subscriptions/{subscriptionId}/update-payment-method (API reference)

curl 'https://api.neonpay.com/subscriptions/SUB-06B4K3-MW11RC-V25A3K-MQT063G0/update-payment-method' \
  -X POST \
  -H 'x-api-key: {{your API key}}'

200 OK
{
  "redirectUrl": "https://checkout.neonpay.com/en-US/subscription/SUB-.../update-payment-method?token=...",
  "token": "...",
  "subscription": { "token": "..." },
  "expiresAt": "2026-07-01T17:00:00.000Z"
}

Redirect the user to redirectUrl. They will enter their new card details on Neon's hosted page. If 3D Secure is required, it is handled in an overlay - the user never leaves the page. On completion, Neon shows a success or error message. The link expires after 60 minutes.

To send the user back to your site after the update, pass a returnUrl as body parameter:

curl 'https://api.neonpay.com/subscriptions/SUB-06B4K3-MW11RC-V25A3K-MQT063G0/update-payment-method' \
  -X POST \
  -H 'content-type: application/json' \
  -H 'x-api-key: {{your API key}}' \
  -d '{ "returnUrl": "https://example.com/payment-updated" }'

Neon appends subscriptionId, subscriptionToken, and updatePaymentMethodToken as query parameters to your returnUrl.

📘 To confirm the update succeeded you may call GET /subscriptions/{subscriptionId} on returnUrl.

Refunds

If you'd like to cancel a subscription immediately, and give the user a pro-rated refund, contact your Neon representative and we'll get that configured for you.


Did this page help you?