> ## 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 credits to a client

> Adds credits to one client's account and returns their new balance.
Use it for reactivation campaigns, loyalty rewards, or manual
corrections.

The grant is written in a single transaction. Unless you set
`sendEmail` to `false`, the client receives a notification email.

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




## OpenAPI

````yaml /api/v1/openapi.yaml post /v1/clients/{clientId}/credits
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}/credits:
    post:
      tags:
        - Credits and passes
      summary: Grant credits to a client
      description: |
        Adds credits to one client's account and returns their new balance.
        Use it for reactivation campaigns, loyalty rewards, or manual
        corrections.

        The grant is written in a single transaction. Unless you set
        `sendEmail` to `false`, the client receives a notification email.

        See [Granting credits and passes](/guides/granting-credits) for the
        end-to-end flow.
      operationId: addCreditsToClient
      parameters:
        - $ref: '#/components/parameters/ClientId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AddCreditsRequest'
            example:
              customEntryCount:
                count: 10
                validityTimeValue: 1
                validityTimeUnit: month
              currency: CZK
              price: 0
              sendEmail: false
      responses:
        '200':
          description: The client's new credit balance.
          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/AddCreditsResponse'
              example:
                statusCode: 200
                message: Success
                data:
                  clientId: 123
                  numberOfCredits: 510
                  validTo: '2026-10-01'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/ForbiddenUltimate'
        '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:
    AddCreditsRequest:
      type: object
      required:
        - customEntryCount
        - currency
        - price
      properties:
        customEntryCount:
          $ref: '#/components/schemas/CustomEntryCount'
        currency:
          type: string
          description: >-
            Currency code recorded on the grant. Send the studio's configured
            currency, typically an ISO 4217 code such as `CZK`, `EUR`, or `USD`.
            The value is stored as sent and its format is not validated, so a
            typo is recorded rather than rejected. Send `price: 0` for a gift.
          example: CZK
        price:
          type: number
          minimum: 0
          description: What the client paid. Send `0` for a gift or a reward.
        sendEmail:
          type: boolean
          default: true
          description: Set to `false` to grant silently, with no notification email.
    AddCreditsResponse:
      type: object
      properties:
        statusCode:
          type: integer
          example: 200
        message:
          type: string
          example: Success
        data:
          type: object
          properties:
            clientId:
              type: integer
            numberOfCredits:
              type: integer
              description: The client's credit balance after the grant.
            validTo:
              type: string
              format: date
              nullable: true
              description: New expiry of the client's credits.
    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:
    BadRequest:
      description: >-
        The request is malformed — a required parameter is missing, the
        `Authorization` header does not use the Bearer scheme, or body
        validation failed.
      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: 'dateFrom parameter is required (format: YYYY-MM-DD)'
    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' )
    ForbiddenUltimate:
      description: >-
        Your studio's plan does not allow the private API — it requires the
        Ultimate plan. 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'
          example:
            statusCode: 403
            error: Error
            message: The Zenamu API is only available on the Ultimate tariff.
    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).

````