> ## Documentation Index
> Fetch the complete documentation index at: https://docs.useplinth.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Create a subscription

> Subscribes a customer to a plan. If the plan has a trial period, the subscription starts in `trialing` state and the first charge fires at `trial_end_at`. Use `preferred_rail: transfer` for customers who pay by bank transfer.




## OpenAPI

````yaml POST /v1/subscriptions
openapi: 3.0.3
info:
  title: Plinth API
  version: 0.9.0
  description: >
    Recurring billing for Nigerian SaaS — card charging, bank transfers via
    virtual accounts,

    proration, dunning, and recovery in one API.


    All amounts are in **kobo** (1/100th of a Naira). ₦5,000 = `500000`.
servers:
  - url: https://api.useplinth.com
    description: Production
  - url: http://localhost:7331
    description: Local development
security:
  - BearerAuth: []
tags:
  - name: Sandbox
    description: Create an isolated sandbox environment for testing. No auth required.
  - name: Customers
    description: Who you are billing. One customer can have multiple subscriptions.
  - name: Plans
    description: Plan groups and the plans within them. Customers subscribe to plans.
  - name: Subscriptions
    description: The recurring billing relationship between a customer and a plan.
  - name: Virtual Accounts
    description: Dedicated bank account numbers for customers who pay by transfer.
  - name: Invoices
    description: Created at each billing cycle. Tracks what a customer owes for a period.
  - name: Webhooks
    description: >-
      Register endpoints that receive signed, retried events. See Receiving
      webhooks.
  - name: Admin
    description: Test clock control, billing tick, and suspense resolution. Test-mode only.
paths:
  /v1/subscriptions:
    post:
      tags:
        - Subscriptions
      summary: Create a subscription
      description: >
        Subscribes a customer to a plan. If the plan has a trial period, the
        subscription starts in `trialing` state and the first charge fires at
        `trial_end_at`. Use `preferred_rail: transfer` for customers who pay by
        bank transfer.
      operationId: create-subscription
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - customer_id
                - plan_id
              properties:
                customer_id:
                  type: string
                  example: cus_01JABC...
                plan_id:
                  type: string
                  example: pln_01JABC...
                default_payment_method_id:
                  type: string
                  description: Card token from Nomba. Required for card-rail subscriptions.
                  example: tok_test_visa
                preferred_rail:
                  type: string
                  enum:
                    - card
                    - transfer
                    - direct_debit
                  default: card
                  example: card
                quantity:
                  type: integer
                  default: 1
                  example: 1
                metadata:
                  type: object
                  additionalProperties: true
      responses:
        '201':
          description: Subscription created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Subscription'
              example:
                object: subscription
                id: sub_01JABC...
                state: active
                current_period_start: '2026-06-01T00:00:00Z'
                current_period_end: '2026-07-01T00:00:00Z'
                trial_end_at: null
                next_bill_at: '2026-07-01T00:00:00Z'
components:
  schemas:
    Subscription:
      type: object
      properties:
        object:
          type: string
          enum:
            - subscription
        id:
          type: string
          example: sub_01JABC...
        state:
          type: string
          enum:
            - incomplete
            - active
            - trialing
            - past_due
            - grace
            - delinquent
            - paused
            - canceled
          example: active
        current_period_start:
          type: string
          format: date-time
        current_period_end:
          type: string
          format: date-time
        trial_end_at:
          type: string
          format: date-time
          nullable: true
        next_bill_at:
          type: string
          format: date-time
        cancel_at_period_end:
          type: boolean
          description: >-
            True when the subscription is set to cancel at period end (still
            active until then).
          example: false
        canceled_at:
          type: string
          format: date-time
          nullable: true
        has_card:
          type: boolean
          description: Whether a card token is on file. Transfer-funded subs have none.
          example: true
        scheduled_change:
          type: object
          nullable: true
          description: A pending period-end plan change (e.g. a scheduled downgrade).
          properties:
            id:
              type: string
            new_plan_id:
              type: string
            new_quantity:
              type: integer
            scheduled_for:
              type: string
              format: date-time
              nullable: true
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: >
        Use `sk_test_` keys for sandbox. Use `sk_live_` keys for production.
        Obtain your key from the dashboard.

````