> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.trygrant.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.trygrant.com/_mcp/server.

# Subscription checkout

A subscription signup link gives one customer a hosted checkout page for one plan. Your server creates the link with a Grant API key, then sends the returned URL to that customer.

Each link is tied to a customer and plan and expires 24 hours after creation. You can use the same endpoint to start a subscription or change an existing subscription to another plan.

## Before you begin

You need:

* A customer in Grant.
* A billing plan with a `plan_code` and its fees set up.
* Payment processing configured for the company in Grant.
* A server-side Grant API key. Never create signup links from browser code.

## Start a subscription

Create a link with the customer ID and the plan code. You can also set where the hosted page sends the customer after success or when they go back.

```bash
curl -X POST https://api.trygrant.com/v1/subscription-signup-links \
  -H "Authorization: Bearer ak_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_id": "cm5x9z8nv0001h85r7l9p2k2m",
    "plan_code": "starter_plan",
    "success_url": "https://example.com/billing/success",
    "back_url": "https://example.com/pricing"
  }'
```

The response includes the hosted checkout URL and its expiry time.

```json title="Response"
{
  "success": true,
  "subscription_signup_link": {
    "id": "cm5x9z8nv0000h85r7l9p2k1m",
    "customer_id": "cm5x9z8nv0001h85r7l9p2k2m",
    "plan_id": "cm5x9z8nv0002h85r7l9p2k3m",
    "plan_code": "starter_plan",
    "url": "https://www.trygrant.com/subscribe/opaque-token",
    "token_expiration": "2026-08-07T12:00:00.000Z",
    "success_url": "https://example.com/billing/success",
    "back_url": "https://example.com/pricing",
    "previous_subscription_id": null,
    "change_timing_mode": null,
    "cancel_now_prepaid_refund_policy": null,
    "created_at": "2026-08-06T12:00:00.000Z"
  },
  "request_id": "req_abc123"
}
```

Send `subscription_signup_link.url` only to the customer named in the request. Do not put the URL in public pages, logs, or analytics events because it contains the checkout token.

See [Create a subscription signup link](/api-reference/grant-events-api/subscription-signup-links/create) for the full request and response.

## Change an existing subscription

Pass `previous_subscription_id` and `change_timing_mode` to use checkout for a plan change. The old subscription must belong to the customer and have an `active`, `trialing`, or `past_due` status.

```bash
curl -X POST https://api.trygrant.com/v1/subscription-signup-links \
  -H "Authorization: Bearer ak_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_id": "cm5x9z8nv0001h85r7l9p2k2m",
    "plan_code": "growth_plan",
    "previous_subscription_id": "cm5x9z8nv0009h85r7l9p2k9m",
    "change_timing_mode": "now",
    "cancel_now_prepaid_refund_policy": "no_refund_prepaid_fixed_fees",
    "success_url": "https://example.com/billing/success"
  }'
```

Choose the timing that fits the plan change:

* `now` changes the plan after checkout. You can set `cancel_now_prepaid_refund_policy` to `no_refund_prepaid_fixed_fees` or `refund_prorated_prepaid_fixed_fees`.
* `end_of_period` schedules the new plan for the current period's end and does not charge the customer during checkout. Do not send `cancel_now_prepaid_refund_policy` with this mode.

## What the customer sees

The hosted page shows the plan, its fees, the amount due today, and the payment form. For an end-of-period plan change, it shows the planned charge and date instead of charging at checkout.

If the customer already has an active subscription to the target plan, Grant shows that the plan is already active.

## Redirect the customer

* `success_url` sends the customer back to your app after Grant confirms the subscription or scheduled plan change.
* `back_url` sets the destination of the back action on the hosted page.

Do not treat the browser redirect as proof that the subscription changed. Read the [subscription](/api-reference/grant-events-api/subscriptions/get) from your server before you grant access or show the new plan as active.

## What happens after confirmation

1. Grant attaches the payment method to the customer and sets it as the default.
2. For a new subscription, Grant creates the subscription, finalizes the first invoice, and charges any amount due.
3. For an immediate plan change, Grant changes the plan and charges any amount due after the selected prepaid-fee policy.
4. For an end-of-period change, Grant schedules the target plan and does not charge during checkout.
5. If `success_url` is set, the hosted page sends the customer there after the change finishes or gets scheduled.

## Good practices

* Create each link on your server for the exact customer and plan you intend to offer.
* Show the plan, price, timing, and refund rule before you send the customer to checkout.
* Use HTTPS redirect URLs in production.
* Treat the signup URL as a secret until it expires.
* Create a new link when the customer changes plans or the old link expires.