---
title: "Trial Signup & Card Gate"
description: "New signups require a payment card via a 3-day trial checkout — how the card gate works for email and OAuth signups"
canonical: "https://docs.ainative.studio/docs/getting-started/trial-signup"
last-updated: "2026-10-22T17:48:46.689Z"
---

# Trial Signup & Card Gate

Source: https://docs.ainative.studio/docs/getting-started/trial-signup

> New signups require a payment card via a 3-day trial checkout — how the card gate works for email and OAuth signups

# Trial Signup & Card Gate

New human signups on AINative Studio go through a **card-gated 3-day free trial**. A valid payment card must be attached through a Stripe Checkout session before the account is created. This applies to **both** email/password signups and OAuth signups (GitHub, Google, LinkedIn).

:::note Who is gated
The card gate applies to interactive human signups. **Keyless** signup sources are exempt by design: Instant DB and agent signups (agents cannot enter a card), and the AINative Builder (which captures the card later, at the Live/upgrade step). The gate is also controlled server-side by the `REQUIRE_TRIAL_CARD` flag.
:::

## How the gate behaves

When a signup is subject to the gate and no verified checkout session is present, the register/callback request is rejected with **HTTP 402 Payment Required** and a structured body:

```json
{
  "code": "TRIAL_CARD_REQUIRED",
  "error_code": "TRIAL_CARD_REQUIRED",
  "message": "A credit card and 3-day trial are required to sign up. Start your trial to continue.",
  "checkout_endpoint": "/api/v1/auth/create-trial-checkout",
  "email": "user@example.com"
}
```

The `email` is echoed back so an OAuth callback (which has no signup form) can open trial checkout for the right user. On receiving a 402 with `error_code: TRIAL_CARD_REQUIRED`, send the user to trial checkout.

## Starting trial checkout

Create a Stripe Checkout session for the trial:

```bash
POST /api/v1/auth/create-trial-checkout
Content-Type: application/json

{
  "email": "user@example.com",
  "name": "Jane Developer",
  "plan": "Pro",
  "provider": "github"
}
```

| Field | Required | Description |
|-------|----------|-------------|
| `email` | Yes | Email the account will be created under |
| `name` | No | Display name |
| `plan` | No | Selected plan (`Pro`, `Business`, `Hobbyist`; aliases resolve). Drives the Stripe price. Omit → Hobbyist |
| `provider` | No | `github`, `google`, or `linkedin` for OAuth signups, so the post-payment resume returns to the OAuth callback instead of the email finalizer |

**Response:**
```json
{
  "checkout_url": "https://checkout.stripe.com/c/pay/cs_...",
  "session_id": "cs_test_...",
  "customer_id": "cus_..."
}
```

Redirect the user to `checkout_url`. A card is required up front; the trial cancels automatically if no card is attached (anti-farming).

## Finishing signup

After the card is captured, Stripe returns to the finalizer with the checkout session id:

- **Email signups:** `/signup?stripe_session_id={CHECKOUT_SESSION_ID}` → the page calls `POST /api/v1/auth/register` with the `stripe_session_id`.
- **OAuth signups:** `/login/callback?provider={provider}&stripe_session_id={CHECKOUT_SESSION_ID}` → the callback re-runs the gate with the verified session.

The backend verifies the session with Stripe (it must exist, be `complete`, and match the signup email) before creating the account. A card already backing another active subscription, or a prepaid card, is rejected with a 402 (`TRIAL_CARD_VELOCITY` / `TRIAL_CARD_REQUIRED`).

## Related endpoints

| Endpoint | Method | Purpose |
|----------|--------|---------|
| `/api/v1/auth/create-trial-checkout` | POST | Start the card-gated trial checkout session |
| `/api/v1/auth/register` | POST | Finalize an email signup (pass `stripe_session_id`) |

See [Authentication](/docs/getting-started/authentication) for JWT, API key, and OAuth details.
