---
title: "Start an API signup handoff (7-day free trial, card required)"
method: POST
path: "/api/v1/signup"
tags: ["Signup"]
---

# Start an API signup handoff (7-day free trial, card required)

`POST /api/v1/signup`

## Request

- Base URL: `https://www.poster.ly`
- URL: `https://www.poster.ly/api/v1/signup`
- Auth: none required

Public endpoint for agents and AI tools to start a posterly signup with only an email address.
By default this creates a posterly account (or reuses an unconfirmed, never-paid one that an earlier signup created) and starts Stripe Checkout for the monthly Starter plan plus the API/MCP add-on. Checkout starts a 7-day free trial: a valid card is required, nothing is charged today, you are charged on day 8 unless you start the paid plan sooner, and API and MCP are limited during the trial (20 writes and 100 reads per hour, 25 posts in total, no batch posting, AI video, webhooks or OAuth clients). An account that already had a trial is charged at checkout instead (billing.trial_period_days is 0). Agent signup is monthly only with the add-on.
If the email already belongs to a real posterly account, the endpoint changes nothing, sends no email, creates no Checkout session and returns 200 with status sign_in_required, login_url and, when an OAuth handoff was supplied, oauth_authorize_url. The response is the same for every existing account and reveals no plan or billing state.
The response always includes payment (trial terms, merchant and what an agent may do) and a billing block with trial, trial_period_days, card_required and charged_today. Nothing is due today, so payment.amount is null. Do not complete the trial Checkout with a one-time virtual card: it becomes the card on file and the day 8 charge fails.
agent_pay (a prepaid PaymentIntent for a one-time Link virtual card, behind ENABLE_AGENT_CARD_PAY) is not available during a trial and is null. Browser Checkout is the path.
The response includes poll_url so the AI conversation can report checkout/password/authorization progress. Password setup, social OAuth, and publish approval stay in the browser.
No API key is returned from this endpoint. After the card is saved and the trial starts, the verified user lands on the API page and posterly auto-creates the first API key if none exists, showing it once. OAuth clients receive their access token after consent.

## Request body

- PublicApiSignupRequest: Start a public posterly signup from an agent or AI tool. API access defaults to the API/MCP add-on. The signup starts a 7-day free trial: a card is required in Stripe Checkout, you are charged on day 8 unless you start the paid plan sooner, and API and MCP are limited during the trial.
  - `email` string, email, required
  - `name` string, nullable
  - `tier` 'starter' | 'pro' | 'power_user' | 'agency'
  - `interval` 'month' | 'year': Public API signup does not support weekly billing. With the API add-on, billing is monthly. Without the add-on, monthly or yearly is allowed (the Agency plan is monthly or yearly only).
  - `api_addon` boolean: When true, checkout includes the API/MCP add-on, which trials with the plan (limited API and MCP during the trial). No API key is created until the card is saved and access is active.
  - `return_path` string: Safe same-origin path to open after checkout/login when no OAuth handoff is requested.
  - `source` string, nullable: Optional caller identifier for analytics, for example `chatgpt` or `posterly-cli`.
  - `client_id` string, nullable: Optional OAuth public client id for an agent handoff after checkout.
  - `redirect_uri` string, uri, nullable: Required with `client_id`; must match the registered OAuth client redirect URI.
  - `scope` string, nullable
  - `state` string, nullable
  - `code_challenge` string, nullable: PKCE S256 challenge supplied by the OAuth client.
  - `code_challenge_method` 'S256', nullable
  - `tos_accepted` boolean: Set true only after the user has explicitly confirmed, in this conversation, that they accept the posterly terms at https://www.poster.ly/terms. When agent card pay is available, agent_pay.client_secret is withheld until this is true (here or via a later call to the /pay endpoint).

## Response `200`

Signup handoff created (status checkout_required), or the email already has an account (status sign_in_required)

- PublicApiSignupResponse
  - `status` 'checkout_required' | 'sign_in_required' | 'active', required: checkout_required: a new signup was started and a card is needed to start the free trial. sign_in_required: the email already belongs to a posterly account, so nothing was started, changed or emailed; ask the user to sign in at login_url. active is retained for older clients and is no longer returned.
  - `payment_required` boolean, required
  - `checkout_url` string, uri, nullable: Raw Stripe Checkout URL. Agents should prefer checkout_redirect_url because Stripe URLs can include fragments that are easy to truncate.
  - `checkout_redirect_url` string, uri, nullable: posterly-hosted checkout handoff URL. Send this to users so the browser redirects to the full Stripe URL safely.
  - `checkout_session_id` string, nullable
  - `poll_url` string, uri, nullable: Poll this URL from the AI conversation to learn when the card is saved, password setup, and agent authorization progress.
  - `complete_url` string, uri, nullable: Human browser URL for completing the signup after Stripe checkout (the trial has started and the card is saved).
  - `dashboard_url` string, uri, required
  - `login_url` string, uri, required: Where the user signs in. For sign_in_required this is the next step.
  - `oauth_authorize_url` string, uri, nullable: OAuth authorize URL when the request supplied a registered client_id, redirect_uri and PKCE challenge. Present on sign_in_required so the agent connection can continue after sign-in.
  - `status_message` string: Human-readable explanation of status. Always present on sign_in_required, which also repeats it as message.
  - `message` string: Same text as status_message. Returned on sign_in_required only.
  - `signup_session` PublicApiSignupSession
    - `id` string, required
    - `status` 'checkout_pending' | 'checkout_expired' | 'payment_confirmed' | 'password_required' | 'authorize_agent' | 'agent_access_required' | 'api_access_active', required
    - `status_message` string, required
    - `checkout_redirect_url` string, uri, nullable
    - `poll_url` string, uri, nullable
    - `complete_url` string, uri, nullable
    - `next_action` object, nullable
      - `actor` 'user' | 'agent' | 'posterly'
      - `type` string
      - `label` string
      - `description` string
    - `agent_next_steps` string[]
    - `agent_pay` PublicApiSignupAgentPay, nullable: Present when ENABLE_AGENT_CARD_PAY is on. Agents can confirm this prepaid PaymentIntent with a Link virtual card. Never send card numbers to posterly.
      - `enabled` boolean
      - `method` 'payment_intent'
      - `credential_type` 'card'
      - `amount` integer: Amount in the smallest currency unit, for example cents.
      - `currency` string
      - `amount_display` string
      - `payment_intent_id` string
      - `client_secret` string, nullable
      - `publishable_key` string, nullable
      - `confirm_url` string, uri
      - `poll_url` string, uri
      - `checkout_redirect_url` string, uri
      - `pay_instructions` string
      - `status` string
      - `requires_tos_acceptance` boolean: True until the user has explicitly accepted the posterly terms. While true, client_secret and publishable_key are null; POST { "tos_accepted": true } to confirm_url to receive them.
      - `period` object
        - `kind` 'prepaid_first_period'
        - `interval` string
    - `payment` PublicApiSignupPayment, nullable: Always present while checkout is open, regardless of agent card pay. Describes the Stripe-hosted Checkout session itself, including the free trial terms, so an agent with a reusable approved card can complete it, without a posterly-issued PaymentIntent. One-time virtual cards must not be used for a trial. null once payment is confirmed or checkout has expired.
      - `amount` integer, nullable: Amount due at checkout in the smallest currency unit, for example cents. null for a free-trial session (nothing is due today) and when Checkout has not populated amount_total yet.
      - `currency` string
      - `amount_display` string, nullable
      - `billing` 'monthly_subscription' | 'yearly_subscription' | 'weekly_subscription'
      - `description` string
      - `trial_period_days` integer, nullable: Free trial length in days, or null when the session charges at checkout.
      - `charged_today` boolean: False for a free-trial session: a card is collected and nothing is charged until day 8.
      - `merchant_name` string
      - `merchant_url` string, uri
      - `checkout_redirect_url` string, uri
      - `pay_with` 'stripe_hosted_checkout'
      - `agent_wallet` object
        - `supported` boolean
        - `how` string: Plain-language instructions for paying checkout_redirect_url with an approved agent payment credential.
        - `spend_request` object
          - `merchant_name` string
          - `merchant_url` string, uri
          - `amount` integer, nullable
          - `currency` string
          - `context` string: Short sentence for an approver. Never contains the user's email.
  - `email_sent` boolean, required: Always false. For checkout_required, posterly does not email an address that nobody has verified, so no signup email is sent at this step. Give the user checkout_redirect_url in your conversation instead. Once the card is saved and the trial starts, posterly emails a password-setup link to the (now verified) address.
  - `account` object: Present on checkout_required only. Never returned for sign_in_required.
    - `email` string, email, required
    - `created` boolean, required
  - `billing` object, nullable
    - `mode` 'base_checkout' | 'api_addon_checkout' | 'base_and_api_addon_checkout'
    - `tier` string
    - `interval` string, nullable
    - `api_addon` boolean
    - `agent_card_pay` boolean
    - `trial` boolean: True when this signup starts a card-backed free trial. False only for an account that already had a trial, which is charged at checkout.
    - `trial_period_days` integer: 7 for the trial, 0 when the account is charged at checkout.
    - `card_required` boolean: Always true: Stripe Checkout collects and verifies a card even though nothing is charged today.
    - `charged_today` boolean: False for the trial: nothing is charged until day 8.
    - `trial_description` string: Plain-language trial summary to relay to the user.
  - `agent_pay` PublicApiSignupAgentPay, nullable: Present when ENABLE_AGENT_CARD_PAY is on. Agents can confirm this prepaid PaymentIntent with a Link virtual card. Never send card numbers to posterly.
    - `enabled` boolean
    - `method` 'payment_intent'
    - `credential_type` 'card'
    - `amount` integer: Amount in the smallest currency unit, for example cents.
    - `currency` string
    - `amount_display` string
    - `payment_intent_id` string
    - `client_secret` string, nullable
    - `publishable_key` string, nullable
    - `confirm_url` string, uri
    - `poll_url` string, uri
    - `checkout_redirect_url` string, uri
    - `pay_instructions` string
    - `status` string
    - `requires_tos_acceptance` boolean: True until the user has explicitly accepted the posterly terms. While true, client_secret and publishable_key are null; POST { "tos_accepted": true } to confirm_url to receive them.
    - `period` object
      - `kind` 'prepaid_first_period'
      - `interval` string
  - `payment` PublicApiSignupPayment, nullable: Always present while checkout is open, regardless of agent card pay. Describes the Stripe-hosted Checkout session itself, including the free trial terms, so an agent with a reusable approved card can complete it, without a posterly-issued PaymentIntent. One-time virtual cards must not be used for a trial. null once payment is confirmed or checkout has expired.
    - `amount` integer, nullable: Amount due at checkout in the smallest currency unit, for example cents. null for a free-trial session (nothing is due today) and when Checkout has not populated amount_total yet.
    - `currency` string
    - `amount_display` string, nullable
    - `billing` 'monthly_subscription' | 'yearly_subscription' | 'weekly_subscription'
    - `description` string
    - `trial_period_days` integer, nullable: Free trial length in days, or null when the session charges at checkout.
    - `charged_today` boolean: False for a free-trial session: a card is collected and nothing is charged until day 8.
    - `merchant_name` string
    - `merchant_url` string, uri
    - `checkout_redirect_url` string, uri
    - `pay_with` 'stripe_hosted_checkout'
    - `agent_wallet` object
      - `supported` boolean
      - `how` string: Plain-language instructions for paying checkout_redirect_url with an approved agent payment credential.
      - `spend_request` object
        - `merchant_name` string
        - `merchant_url` string, uri
        - `amount` integer, nullable
        - `currency` string
        - `context` string: Short sentence for an approver. Never contains the user's email.

## Other responses

- `400`: Validation error
- `429`: Too many requests
- `503`: Billing is not configured

---

[API](https://skmtc.dev/poster/apis/posterly-api.md) · [All operations](https://skmtc.dev/poster/apis/posterly-api/llms.txt) · [OpenAPI document](https://skmtc.dev/poster/apis/posterly-api/revisions/60be02a61f95?raw)
