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

# Create a revenue account

> Adds an account to the chart of accounts. `code` is what the club's bookkeeper reconciles against and must be free within the organization - a clash is a 409, not a second account under the same code.

Sending `isDefault: true` moves the default off whichever account currently holds it, in the same transaction and behind a per-organization lock, so concurrent promotions cannot both win. The default is where a sale posts when the item names no account, resolved at the time of the sale rather than frozen onto the item, so moving it changes where future unattributed sales land and leaves the ones already taken alone.

Two things about the default are decided for you. An organization whose chart has no default yet gets one from this call whatever `isDefault` says, since creating an account is the only way to give it one - so the first account in an empty chart is always the default, and is therefore always created active. And a default can never be inactive, so `isActive: false` is refused for any request that would land one, whether `isDefault` was sent or inferred.

Requires `revenue-accounts:write`. Supports the `Idempotency-Key` header.




## OpenAPI

````yaml /openapi-platform.json post /v1/platform/revenue-accounts
openapi: 3.0.0
info:
  title: 1club Platform API
  version: 1.0.0
  description: >-
    The 1club Platform API lets you programmatically access and manage your
    organization's data.


    ## Official API Contract


    This documentation is the official source of truth for the 1club Platform
    API.

    If an integration relies on undocumented endpoints, fields, response shapes,
    or internal behavior outside this spec, we can't guarantee backward
    compatibility.

    Build against what's documented here to stay stable as the platform evolves.


    ## Authentication


    All requests require a customer API key passed as a Bearer token:


    ```

    Authorization: Bearer 1club_sk_live_...

    ```


    Generate API keys from the admin portal under **Settings > API Tokens**.

    The key is tied to your organization - all responses are scoped to your
    org's data.


    ## Rate Limiting


    - **100 requests per minute** per API key

    - When exceeded, the API returns `429 Too Many Requests` with a
    `Retry-After` header

    - Rate limit headers are included in every response:
      - `X-RateLimit-Limit` - max requests per window
      - `X-RateLimit-Remaining` - requests remaining
      - `X-RateLimit-Reset` - seconds until the window resets

    ## Errors


    | Status | Meaning |

    |--------|---------|

    | `400` | Invalid request parameters |

    | `401` | Missing or invalid API key |

    | `404` | Resource not found (or doesn't belong to your organization) |

    | `429` | Rate limit exceeded |

    | `500` | Internal server error |
  contact:
    name: 1club API Support
    email: support@1club.ai
servers:
  - url: https://api.1club.ai
    description: Production API
security:
  - customerApiAuth: []
tags: []
paths:
  /v1/platform/revenue-accounts:
    post:
      tags:
        - Revenue Accounts
      summary: Create a revenue account
      description: >
        Adds an account to the chart of accounts. `code` is what the club's
        bookkeeper reconciles against and must be free within the organization -
        a clash is a 409, not a second account under the same code.


        Sending `isDefault: true` moves the default off whichever account
        currently holds it, in the same transaction and behind a
        per-organization lock, so concurrent promotions cannot both win. The
        default is where a sale posts when the item names no account, resolved
        at the time of the sale rather than frozen onto the item, so moving it
        changes where future unattributed sales land and leaves the ones already
        taken alone.


        Two things about the default are decided for you. An organization whose
        chart has no default yet gets one from this call whatever `isDefault`
        says, since creating an account is the only way to give it one - so the
        first account in an empty chart is always the default, and is therefore
        always created active. And a default can never be inactive, so
        `isActive: false` is refused for any request that would land one,
        whether `isDefault` was sent or inferred.


        Requires `revenue-accounts:write`. Supports the `Idempotency-Key`
        header.
      parameters:
        - in: header
          name: Idempotency-Key
          schema:
            type: string
            maxLength: 255
          description: >-
            Retry-safe key; a repeat of the same request replays the first
            response
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PlatformRevenueAccountCreate'
      responses:
        '201':
          description: Revenue account created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlatformRevenueAccount'
        '400':
          $ref: '#/components/responses/PlatformBadRequest'
        '401':
          $ref: '#/components/responses/PlatformUnauthorized'
        '403':
          description: API key is missing the required `revenue-accounts:write` scope
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlatformError'
        '409':
          description: Another account in this organization already uses that `code`
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlatformError'
        '429':
          $ref: '#/components/responses/PlatformRateLimited'
      security:
        - customerApiAuth: []
components:
  schemas:
    PlatformRevenueAccountCreate:
      type: object
      description: >-
        Fields accepted when creating a revenue account. `name` and `code` are
        required, and the code must be free within the organization. Unknown
        fields are rejected. The billing entity an account belongs to is not
        settable here - it is inherited, and re-pointing one rewrites who is
        selling.
      required:
        - name
        - code
      properties:
        name:
          type: string
          maxLength: 255
        code:
          type: string
          maxLength: 50
          description: >-
            The bookkeeper's code for the account, e.g. "4000". Unique within
            the organization; a clash is a 409.
        description:
          type: string
          nullable: true
          maxLength: 2000
        isActive:
          type: boolean
          default: true
          description: >-
            False retires the account. Everything already pointing at it keeps
            pointing at it; there is no delete. Refused for any request that
            would leave the default inactive - including the first account in an
            empty chart, which is always made the default.
        isDefault:
          type: boolean
          default: false
          description: >-
            Where a sale posts when the item names no account. Setting it true
            moves the default off whichever account currently holds it, in the
            same transaction and behind a per-organization lock. Ignored when
            the chart has no default yet - the first account always takes it,
            since creating one is the only way to give the organization a
            default. The default must be active, so anything landing an inactive
            one is refused.
    PlatformRevenueAccount:
      type: object
      description: >-
        One account in the organization's chart of accounts. Reference the `id`
        as `revenueAccountId` on a membership plan, a product, a class type, an
        area type or an instructor type to decide where its sales post.
      properties:
        id:
          type: integer
        name:
          type: string
        code:
          type: string
          description: >-
            The chart-of-accounts code, which is how the club's bookkeeper names
            the account. Unique within the organization.
        description:
          type: string
          nullable: true
        isActive:
          type: boolean
          description: >-
            False for an account retired from the chart. Still valid on existing
            rows; do not attach it to something new. Never false on the default.
        isDefault:
          type: boolean
          description: >-
            Where a sale posts when nothing on the item names an account.
            Exactly one account holds it, and it is always active.
    PlatformError:
      type: object
      properties:
        error:
          type: string
  responses:
    PlatformBadRequest:
      description: Invalid request (bad parameters, or a body that fails validation)
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/PlatformError'
    PlatformUnauthorized:
      description: Invalid or missing API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/PlatformError'
    PlatformRateLimited:
      description: Rate limit exceeded
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/PlatformError'
  securitySchemes:
    customerApiAuth:
      type: http
      scheme: bearer
      description: >-
        Organization-scoped bearer credential: a customer API key
        (1club_sk_live_...) or an MCP OAuth access token.

````