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

# Grant entry passes to a client

> Adds entry passes to one client's account and returns their new balance
in the target group.

Send `passGroupId` to choose which [pass group](/api/objects/pass-group)
the entries land in. Omit it, or send `null`, and the entries go to your
studio's default group — the behavior existing integrations rely on.
Explicitly sending that default group's ID behaves the same way.

See [Granting credits and passes](/guides/granting-credits) for the
end-to-end flow.




## OpenAPI

````yaml /api/v1/openapi.yaml post /v1/clients/{clientId}/passes
openapi: 3.0.3
info:
  title: Zenamu API v1
  version: '1.0'
  description: The Zenamu public REST API.
servers:
  - url: https://api.zenamu.com
    description: Production
security:
  - zenamuPublicKey: []
tags:
  - name: Classes
  - name: Workshops
  - name: Lecturers
  - name: Places
  - name: Clients
  - name: Credits and passes
  - name: Pass groups
paths:
  /v1/clients/{clientId}/passes:
    post:
      tags:
        - Credits and passes
      summary: Grant entry passes to a client
      description: |
        Adds entry passes to one client's account and returns their new balance
        in the target group.

        Send `passGroupId` to choose which [pass group](/api/objects/pass-group)
        the entries land in. Omit it, or send `null`, and the entries go to your
        studio's default group — the behavior existing integrations rely on.
        Explicitly sending that default group's ID behaves the same way.

        See [Granting credits and passes](/guides/granting-credits) for the
        end-to-end flow.
      operationId: addPassesToClient
      parameters:
        - $ref: '#/components/parameters/ClientId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AddPassesRequest'
            example:
              customEntryCount:
                count: 3
                validityTimeValue: 1
                validityTimeUnit: month
              currency: CZK
              price: 0
              passGroupId: 42
              sendEmail: false
      responses:
        '200':
          description: The client's new entry balance in the target group.
          headers:
            X-RateLimit-Limit:
              description: Maximum requests allowed in the current one-minute window.
              schema:
                type: integer
                example: 100
            X-RateLimit-Remaining:
              description: Requests remaining in the current window.
              schema:
                type: integer
                minimum: 0
                example: 99
            X-RateLimit-Reset:
              description: Unix timestamp in seconds when the current window resets.
              schema:
                type: integer
                example: 1788336000
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AddPassesResponse'
              example:
                statusCode: 200
                message: Success
                data:
                  clientId: 123
                  numberOfEntries: 11
                  validTo: '2026-10-01'
        '400':
          $ref: '#/components/responses/BadRequestPassGroup'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/ForbiddenPassGrant'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - zenamuSecretKey: []
components:
  parameters:
    ClientId:
      name: clientId
      in: path
      required: true
      schema:
        type: integer
        minimum: 1
        example: 123
      description: >-
        The client's numeric `id`, taken from the `id` field of [`GET
        /v1/clients`](/api/v1/reference/clients/list-clients). This is not the
        opaque `_id`. Malformed values and numeric prefixes return `400`.
  schemas:
    AddPassesRequest:
      type: object
      required:
        - customEntryCount
        - currency
        - price
      properties:
        customEntryCount:
          $ref: '#/components/schemas/CustomEntryCount'
        currency:
          type: string
          example: CZK
        price:
          type: number
          minimum: 0
        passGroupId:
          type: integer
          minimum: 1
          nullable: true
          description: >-
            Target [pass group](/api/objects/pass-group). Omit it or send `null`
            for the studio default group. A group belonging to another studio,
            or an unknown ID, is rejected with `400`.
        sendEmail:
          type: boolean
          default: true
    AddPassesResponse:
      type: object
      properties:
        statusCode:
          type: integer
          example: 200
        message:
          type: string
          example: Success
        data:
          type: object
          properties:
            clientId:
              type: integer
            numberOfEntries:
              type: integer
              description: The client's entry balance in the target group after the grant.
            validTo:
              type: string
              format: date
              nullable: true
    CustomEntryCount:
      type: object
      required:
        - count
        - validityTimeValue
        - validityTimeUnit
      description: How many credits or entries to grant, and for how long.
      properties:
        count:
          type: integer
          minimum: 1
          description: Number of credits or entries to add.
        validityTimeValue:
          type: integer
          minimum: 1
          description: >-
            How many `validityTimeUnit`s the grant stays valid, counted from
            now. Capped per unit: 36500 days, 5200 weeks, 1200 months, 100
            years.
        validityTimeUnit:
          type: string
          enum:
            - day
            - week
            - month
            - year
    ErrorResponse:
      type: object
      required:
        - statusCode
        - message
      properties:
        statusCode:
          type: integer
          description: Repeats the HTTP status code.
        error:
          type: string
          description: >-
            Short label — `Internal Server Error` for `500`, `Too Many Requests`
            for `429`, `Error` otherwise.
        message:
          type: string
          description: >-
            Human-readable explanation. For `500` this is a fixed generic
            message; the detail is logged server-side.
  responses:
    BadRequestPassGroup:
      description: >-
        Body validation failed, or `passGroupId` names a group that does not
        exist in your studio.
      headers:
        X-RateLimit-Limit:
          description: Maximum requests allowed in the current one-minute window.
          schema:
            type: integer
            example: 100
        X-RateLimit-Remaining:
          description: Requests remaining in the current window.
          schema:
            type: integer
            minimum: 0
            example: 99
        X-RateLimit-Reset:
          description: Unix timestamp in seconds when the current window resets.
          schema:
            type: integer
            example: 1788336000
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            statusCode: 400
            error: Error
            message: Pass group not found
    Unauthorized:
      description: No API key was sent.
      headers:
        X-RateLimit-Limit:
          description: Maximum requests allowed in the current one-minute window.
          schema:
            type: integer
            example: 100
        X-RateLimit-Remaining:
          description: Requests remaining in the current window.
          schema:
            type: integer
            minimum: 0
            example: 99
        X-RateLimit-Reset:
          description: Unix timestamp in seconds when the current window resets.
          schema:
            type: integer
            example: 1788336000
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            statusCode: 401
            error: Error
            message: >-
              Missing access token. You must send your access token in the
              request header ('Authorization: Bearer YOUR_ACCESS_TOKEN' )
    ForbiddenPassGrant:
      description: >-
        The studio's plan does not allow the private API, or the request
        explicitly targets a non-default pass group that the plan does not
        include. The group restriction is a top-level `403` only on the
        single-client endpoint; bulk grants report it per item inside `200`. See
        [Plans and access](/api#plans-and-access).
      headers:
        X-RateLimit-Limit:
          description: Maximum requests allowed in the current one-minute window.
          schema:
            type: integer
            example: 100
        X-RateLimit-Remaining:
          description: Requests remaining in the current window.
          schema:
            type: integer
            minimum: 0
            example: 99
        X-RateLimit-Reset:
          description: Unix timestamp in seconds when the current window resets.
          schema:
            type: integer
            example: 1788336000
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            privateApiUnavailable:
              summary: Private API unavailable
              value:
                statusCode: 403
                error: Error
                message: The Zenamu API is only available on the Ultimate tariff.
            passGroupUnavailable:
              summary: Targeted pass group unavailable
              value:
                statusCode: 403
                error: Error
                message: This feature is not available in your current tariff plan
    NotFound:
      description: >-
        The API key was not recognized, or the client named in the path does not
        belong to your studio.
      headers:
        X-RateLimit-Limit:
          description: Maximum requests allowed in the current one-minute window.
          schema:
            type: integer
            example: 100
        X-RateLimit-Remaining:
          description: Requests remaining in the current window.
          schema:
            type: integer
            minimum: 0
            example: 99
        X-RateLimit-Reset:
          description: Unix timestamp in seconds when the current window resets.
          schema:
            type: integer
            example: 1788336000
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            statusCode: 404
            error: Error
            message: Client not found
    TooManyRequests:
      description: >-
        You exceeded 100 calls per minute on this endpoint. See [Rate
        limits](/api/rate-limits).
      headers:
        X-RateLimit-Limit:
          description: Maximum requests allowed in the current one-minute window.
          schema:
            type: integer
            example: 100
        X-RateLimit-Remaining:
          description: Requests remaining in the current window.
          schema:
            type: integer
            minimum: 0
            example: 99
        X-RateLimit-Reset:
          description: Unix timestamp in seconds when the current window resets.
          schema:
            type: integer
            example: 1788336000
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            statusCode: 429
            error: Too Many Requests
            message: 'Rate limit exceeded: up to 100 requests per minute per endpoint.'
    InternalServerError:
      description: >-
        Unexpected server error. Retry with backoff if the call is safe to
        repeat.
      headers:
        X-RateLimit-Limit:
          description: Maximum requests allowed in the current one-minute window.
          schema:
            type: integer
            example: 100
        X-RateLimit-Remaining:
          description: Requests remaining in the current window.
          schema:
            type: integer
            minimum: 0
            example: 99
        X-RateLimit-Reset:
          description: Unix timestamp in seconds when the current window resets.
          schema:
            type: integer
            example: 1788336000
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            statusCode: 500
            error: Internal Server Error
            message: >-
              We apologize, but there was an error on our end. If problems
              persist, please contact us at support@zenamu.com
  securitySchemes:
    zenamuPublicKey:
      type: http
      scheme: bearer
      description: >-
        Your **public API key** (`zen_pub_…`), sent as `Authorization: Bearer
        <key>`. Browser-safe. See [Authentication](/api/authentication).
    zenamuSecretKey:
      type: http
      scheme: bearer
      description: >-
        Your **secret API key** (`zen_live_…`), sent as `Authorization: Bearer
        <key>`. Backend-to-backend only — never expose it in a browser. See
        [Authentication](/api/authentication).

````