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

# Add plan to contract

> Attach a new (or existing) billing plan to a contract.

<Warning>**Not accessible by SystemUser role.** Requires Admin.</Warning>


## OpenAPI

````yaml post /contracts/{contractId}/plans
openapi: 3.0.3
info:
  title: Enso API
  description: >-
    REST API for Enso's billing & metering platform. This reference covers
    endpoints accessible to the SystemUser role — the role used by API
    integrations.
  version: 1.0.0
  license:
    name: Proprietary
servers:
  - url: https://api.getenso.ai
    description: Production
security:
  - bearerAuth: []
tags:
  - name: Apps
    description: Third-party app integrations and credentials
  - name: Attributes
    description: Custom attribute definitions on catalog/customer entities
  - name: Auth
    description: Exchange API credentials for an access token
  - name: Billing
    description: Plans and plan items — what your contracts apply
  - name: Catalog
    description: SKUs and SKU groups — the product taxonomy that plans price against
  - name: Chatbot
    description: Conversational endpoints
  - name: Collections
    description: ''
  - name: Contracts
    description: Contracts that bind a customer to one or more billing plans
  - name: Customers
    description: Manage customer records — the parties Enso bills
  - name: Email templates
    description: Manage email templates
  - name: Entities
    description: Entities (legal entity, contracting organisation) used in billing
  - name: Events
    description: Raw event ingestion — the input to the metering pipeline
  - name: FSM (object lifecycle)
    description: >-
      Drive lifecycle transitions on Invoice/Contract/etc. — used for raise,
      send, mark-paid, etc.
  - name: FX Rates
    description: Currency conversion rates
  - name: Geography
    description: Country/state lookups — reference data for addresses
  - name: Invoices
    description: Invoice CRUD, items, sync, PDF generation, document upload
  - name: Jobs
    description: >-
      Background job orchestration — used by long-running operations like bulk
      sync
  - name: Masters
    description: ''
  - name: Meters
    description: Usage meters — the per-aggregation tally that feeds invoices
  - name: Objects
    description: Generic object schema and query — exposes the data model dynamically
  - name: Organisation
    description: ''
  - name: Organisation attributes
    description: Organisation-level custom attributes
  - name: Organisation settings
    description: Organisation-wide configuration values
  - name: Revenue
    description: Recognised revenue records derived from invoices
  - name: Usage
    description: Usage records — what got billed against each meter for a billing period
  - name: Users
    description: User account read access
paths:
  /contracts/{contractId}/plans:
    post:
      tags:
        - Contracts
      summary: Add plan to contract
      description: Attach a new (or existing) billing plan to a contract.
      operationId: createContractPlan
      parameters:
        - name: contractId
          in: path
          required: true
          description: Contract ID
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ContractPlan'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
        '401':
          description: Unauthorized — token missing or invalid
        '403':
          description: Forbidden — insufficient policy permissions
        default:
          description: Client error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
components:
  schemas:
    ContractPlan:
      type: object
      description: >-
        Use PlanId or planId to reuse an existing billing plan. If neither is
        sent, the route creates a new plan and expects name, and typically
        items.
      properties:
        PlanId:
          type: string
          example: '100'
        planId:
          type: string
          example: '100'
        name:
          type: string
          example: Annual Enterprise Subscription 2026
        startDate:
          type: string
          format: date
          example: '2026-04-01'
        endDate:
          type: string
          format: date
          example: '2027-03-31'
        type:
          type: string
          enum:
            - standard
            - extension
            - renewal
          example: standard
        orderIndex:
          type: integer
          example: 0
        renewalTerms:
          $ref: '#/components/schemas/ContractRenewalTerms'
        ParentContractPlanId:
          type: string
          example: '42'
        parentContractPlanId:
          type: string
          example: '42'
        items:
          type: array
          items:
            $ref: '#/components/schemas/ContractPlanItem'
      required:
        - startDate
      anyOf:
        - required:
            - PlanId
        - required:
            - planId
        - required:
            - name
    SuccessEnvelope:
      type: object
      properties:
        status:
          type: string
          example: success
        message:
          type: string
          example: Success
        data:
          description: Endpoint-specific payload (object, array, or null)
          type: object
          nullable: true
    ErrorEnvelope:
      type: object
      properties:
        status:
          type: string
          example: error
        message:
          type: string
          example: Forbidden
        errors:
          type: array
          items:
            type: object
    ContractRenewalTerms:
      type: object
      properties:
        autoRenewYN:
          type: boolean
          example: false
        renewalNoticePeriodDays:
          type: integer
          minimum: 0
          example: 30
      required:
        - autoRenewYN
    ContractPlanItem:
      type: object
      description: >-
        When creating a new plan item, provide CurrencyId, PlanTypeId, config,
        and either SkuId or Sku. The route persists meter references from
        config.meter and config.quantityMeter.
      properties:
        id:
          type: string
          example: '456'
        orderIndex:
          type: integer
          example: 0
        SkuId:
          type: string
          example: sku_123
        Sku:
          $ref: '#/components/schemas/ContractSku'
        CurrencyId:
          type: string
          example: '2'
        PlanTypeId:
          type: string
          enum:
            - '1'
            - '2'
            - '3'
            - '4'
          description: 1=one_time_fee, 2=recurring_fixed_fee, 3=license_fee, 4=usage_fee.
          example: '3'
        description:
          type: string
          example: Per-user annual license
        config:
          oneOf:
            - $ref: '#/components/schemas/OneTimeContractPlanItemConfig'
            - $ref: '#/components/schemas/RecurringFixedFeeContractPlanItemConfig'
            - $ref: '#/components/schemas/LicenseFeeContractPlanItemConfig'
            - $ref: '#/components/schemas/UsageFeeContractPlanItemConfig'
        milestones:
          type: array
          items:
            $ref: '#/components/schemas/ContractMilestone'
      required:
        - CurrencyId
        - PlanTypeId
        - config
      anyOf:
        - required:
            - SkuId
        - required:
            - Sku
    ContractSku:
      type: object
      properties:
        id:
          type: string
          example: sku_123
        name:
          type: string
          example: Enterprise License
        description:
          type: string
          example: Annual enterprise subscription
        code:
          type: string
          example: ENT-LIC
        Unit:
          $ref: '#/components/schemas/ContractUnit'
      required:
        - name
    OneTimeContractPlanItemConfig:
      type: object
      properties:
        dayOfPeriod:
          type: integer
          minimum: 1
          maximum: 31
          example: 1
        amount:
          type: number
          minimum: 0
          example: 999
        revenueRule:
          type: string
          enum:
            - immediate
            - proportionate
            - milestones
          example: immediate
      required:
        - dayOfPeriod
        - amount
    RecurringFixedFeeContractPlanItemConfig:
      type: object
      properties:
        billingFrequency:
          type: string
          enum:
            - yearly
            - half-yearly
            - quarterly
            - monthly
            - weekly
            - daily
          example: monthly
        anniversaryCycle:
          type: boolean
          example: false
        dayOfCycle:
          oneOf:
            - type: integer
              minimum: 1
              maximum: 31
            - type: string
              enum:
                - L
          example: 1
        monthOfCycle:
          type: integer
          minimum: 1
          maximum: 12
          example: 1
        proration:
          type: boolean
          example: true
        amount:
          type: number
          minimum: 0
          example: 999
        priceIncrementRules:
          $ref: '#/components/schemas/ContractPriceIncrementRules'
        revenueRule:
          type: string
          enum:
            - immediate
            - proportionate
            - milestones
          example: proportionate
      required:
        - billingFrequency
        - anniversaryCycle
        - proration
        - amount
    LicenseFeeContractPlanItemConfig:
      type: object
      properties:
        billingFrequency:
          type: string
          enum:
            - yearly
            - half-yearly
            - quarterly
            - monthly
            - weekly
            - daily
          example: monthly
        anniversaryCycle:
          type: boolean
          example: false
        dayOfCycle:
          oneOf:
            - type: integer
              minimum: 1
              maximum: 31
            - type: string
              enum:
                - L
          example: 1
        monthOfCycle:
          type: integer
          minimum: 1
          maximum: 12
          example: 1
        proration:
          type: boolean
          example: true
        pricingModel:
          type: string
          enum:
            - standard
            - volume
            - tiers
          example: standard
        meter:
          type: string
          description: >-
            Existing meter id. The create-contract flow persists this into
            MeterId via plan item config.
          example: '10'
        prices:
          type: array
          items:
            $ref: '#/components/schemas/ContractPriceSlab'
          minItems: 1
        priceIncrementRules:
          $ref: '#/components/schemas/ContractPriceIncrementRules'
        revenueRule:
          type: string
          enum:
            - immediate
            - proportionate
            - milestones
          example: proportionate
      required:
        - billingFrequency
        - anniversaryCycle
        - pricingModel
        - meter
        - prices
    UsageFeeContractPlanItemConfig:
      type: object
      properties:
        billingFrequency:
          type: string
          enum:
            - yearly
            - half-yearly
            - quarterly
            - monthly
            - weekly
            - daily
          example: monthly
        anniversaryCycle:
          type: boolean
          example: false
        dayOfCycle:
          oneOf:
            - type: integer
              minimum: 1
              maximum: 31
            - type: string
              enum:
                - L
          example: 1
        monthOfCycle:
          type: integer
          minimum: 1
          maximum: 12
          example: 1
        pricingModel:
          type: string
          enum:
            - standard
            - volume
            - tiers
          example: standard
        meter:
          type: string
          description: >-
            Existing meter id. The create-contract flow persists this into
            MeterId via plan item config.
          example: '10'
        quantityMeter:
          type: string
          example: '20'
        prices:
          type: array
          items:
            $ref: '#/components/schemas/ContractPriceSlab'
          minItems: 1
        priceIncrementRules:
          $ref: '#/components/schemas/ContractPriceIncrementRules'
        revenueRule:
          type: string
          enum:
            - immediate
            - proportionate
            - milestones
          example: proportionate
      required:
        - billingFrequency
        - anniversaryCycle
        - pricingModel
        - meter
        - prices
    ContractMilestone:
      type: object
      properties:
        type:
          type: string
          enum:
            - invoice_trigger
            - revenue_trigger
          example: invoice_trigger
        ContractMilestoneId:
          type: string
          example: '123'
        ContractMilestoneData:
          $ref: '#/components/schemas/ContractMilestoneData'
        config:
          $ref: '#/components/schemas/ContractMilestoneConfig'
      required:
        - type
      anyOf:
        - required:
            - ContractMilestoneId
        - required:
            - ContractMilestoneData
    ContractUnit:
      type: object
      properties:
        id:
          type: string
          example: '1'
        name:
          type: string
          example: User
        code:
          type: string
          example: USER
    ContractPriceIncrementRules:
      type: object
      properties:
        enabled:
          type: boolean
          example: true
        incrementCycle:
          type: integer
          minimum: 1
          example: 12
        increment:
          $ref: '#/components/schemas/ContractPriceIncrement'
        incrementKickoffCycle:
          type: integer
          minimum: 1
          example: 2
    ContractPriceSlab:
      type: object
      properties:
        min:
          type: number
          example: 0
        max:
          type: number
          example: 100
        amount:
          type: number
          minimum: 0
          example: 199
        type:
          type: string
          enum:
            - unit
            - package
            - block
            - percentage
          example: unit
        blockSize:
          type: number
          minimum: 1
          example: 100
        pricingFrequency:
          type: string
          enum:
            - yearly
            - half-yearly
            - quarterly
            - monthly
            - weekly
            - daily
          example: monthly
      required:
        - amount
        - type
    ContractMilestoneData:
      type: object
      properties:
        name:
          type: string
          example: Go-live
        description:
          type: string
          example: Production rollout is complete.
        expectedDate:
          type: string
          format: date
          example: '2026-03-31'
        type:
          type: string
          example: manual
      required:
        - name
        - expectedDate
    ContractMilestoneConfig:
      type: object
      properties:
        percentage_of_revenue:
          type: number
          minimum: 0
          maximum: 100
          example: 25
    ContractPriceIncrement:
      type: object
      properties:
        value:
          type: number
          minimum: 0
          example: 5
        type:
          type: string
          enum:
            - percentage
            - absolute
          example: percentage
      required:
        - value
        - type
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        JWT bearer token obtained from POST /auth/system-login using your client
        credentials.

````