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

# Check your API key

> Check that a key works and see the company, scopes and mode it carries. Works with any valid key.

<Tip>
  Call this from each service after deploying or rotating a key, and assert the `mode` you expect.
</Tip>


## OpenAPI

````yaml api-reference/openapi.json GET /v1/ping
openapi: 3.0.0
info:
  title: TeamBuilder API
  description: >-
    The TeamBuilder API gives your own systems access to your company's
    gamification data (employees, leaderboards, departments and the rewards
    shop) and lets you push your employee roster from your HR system. Send every
    request to `https://api.teambuilder.ge/v1` with your API key as
    `Authorization: Bearer <key>`: live keys (`tb_live_…`) work on your real
    data, test keys (`tb_test_…`) on a sandbox company with sample data.
    Responses are JSON with snake_case fields, cursor-based pagination and
    `X-RateLimit-*` headers. For keys, scopes or help, contact
    [contact@teambuilder.ge](mailto:contact@teambuilder.ge).
  version: '1.0'
  contact:
    name: TeamBuilder support
    url: https://teambuilder.ge
    email: contact@teambuilder.ge
servers:
  - url: https://api.teambuilder.ge
    description: Production
security: []
tags:
  - name: Status
    description: Check that your API key works and see what it can access.
  - name: Employees
    description: >-
      Your active employees, their gamification stats and the badges they hold.
      Requires the `employees:read` scope.
  - name: Leaderboard
    description: >-
      XP rankings of your employees for a chosen period, company-wide or grouped
      by department. Requires the `leaderboard:read` scope.
  - name: Departments
    description: Your company's department tree. Requires the `departments:read` scope.
  - name: Shop
    description: >-
      The rewards your employees can redeem with their coins. Requires the
      `shop:read` scope.
  - name: Roster sync
    description: >-
      Keep TeamBuilder in step with your HR system by pushing your employee
      roster. Requires the `employees:write` scope, which is issued on request.
paths:
  /v1/ping:
    get:
      tags:
        - Status
      summary: Check your API key
      description: >-
        Returns the company your API key belongs to, the scopes it grants and
        whether it is a live or a test key.


        Call it when you set up an integration, or from a health check, to
        confirm the key works before you rely on it.


        **Notes**


        - Any valid key may call it: no scope is required.

        - A test key (`tb_test_…`) reports your sandbox company, not your real
        one.
      operationId: ping
      parameters: []
      responses:
        '200':
          description: The key is valid.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
            X-RateLimit-Limit:
              $ref: '#/components/headers/X-RateLimit-Limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/X-RateLimit-Remaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/X-RateLimit-Reset'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiKey'
        '401':
          description: The API key is missing, unknown, revoked or expired.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
            WWW-Authenticate:
              $ref: '#/components/headers/WWW-Authenticate'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: unauthorized
                  message: Invalid API key
                  request_id: req_7Hq2LmX9vT4kPz1RbN8sWc
        '429':
          description: >-
            Your API key made more requests than its limit allows (60 per minute
            unless agreed otherwise), or too many requests came from your IP
            address. Wait `Retry-After` seconds, then retry.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
            X-RateLimit-Limit:
              $ref: '#/components/headers/X-RateLimit-Limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/X-RateLimit-Remaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/X-RateLimit-Reset'
            Retry-After:
              $ref: '#/components/headers/Retry-After'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: rate_limit_exceeded
                  message: Too many requests. Retry after 30 seconds.
                  request_id: req_7Hq2LmX9vT4kPz1RbN8sWc
      security:
        - api-key: []
components:
  headers:
    X-Request-Id:
      description: Unique id of this request. Quote it when you contact support.
      schema:
        type: string
        example: req_7Hq2LmX9vT4kPz1RbN8sWc
    X-RateLimit-Limit:
      description: Requests your API key may make per minute.
      schema:
        type: integer
        example: 60
    X-RateLimit-Remaining:
      description: Requests left in the current one-minute window.
      schema:
        type: integer
        example: 57
    X-RateLimit-Reset:
      description: When the current window ends, as a Unix timestamp in seconds.
      schema:
        type: integer
        example: 1792483260
    WWW-Authenticate:
      description: The authentication scheme to use.
      schema:
        type: string
        example: Bearer realm="TeamBuilder API"
    Retry-After:
      description: Seconds to wait before you retry.
      schema:
        type: integer
        example: 30
  schemas:
    ApiKey:
      type: object
      properties:
        company_id:
          type: string
          format: uuid
          description: Your company in TeamBuilder. For a test key, your sandbox company.
          example: 5f0c2e1a-8b3d-4c7e-9a21-6d4b8e3f1c09
        key_prefix:
          description: >-
            How the key starts: `tb_live_` for a live key, `tb_test_` for a test
            key.
          example: tb_live_
          allOf:
            - $ref: '#/components/schemas/ApiKeyPrefix'
        scopes:
          type: array
          items:
            $ref: '#/components/schemas/ApiKeyScope'
          description: |-
            What the key may access:
            - `employees:read`: employees, their stats and badges.
            - `leaderboard:read`: the leaderboards.
            - `departments:read`: departments.
            - `shop:read`: shop items.
            - `employees:write`: the roster sync.
          example:
            - employees:read
            - leaderboard:read
            - departments:read
            - shop:read
        mode:
          description: >-
            `live` reads and writes your real data; `test` reads and writes your
            sandbox company.
          example: live
          allOf:
            - $ref: '#/components/schemas/ApiKeyMode'
      required:
        - company_id
        - key_prefix
        - scopes
        - mode
    Error:
      type: object
      properties:
        error:
          description: What went wrong, and the id that traces the request.
          allOf:
            - $ref: '#/components/schemas/ErrorDetail'
      description: Every error response has this shape, whatever its status code.
      required:
        - error
    ApiKeyPrefix:
      type: string
      enum:
        - tb_live_
        - tb_test_
      description: >-
        How the key starts: `tb_live_` for a live key, `tb_test_` for a test
        key.
    ApiKeyScope:
      type: string
      enum:
        - employees:read
        - leaderboard:read
        - departments:read
        - shop:read
        - employees:write
      description: |-
        What the key may access:
        - `employees:read`: employees, their stats and badges.
        - `leaderboard:read`: the leaderboards.
        - `departments:read`: departments.
        - `shop:read`: shop items.
        - `employees:write`: the roster sync.
    ApiKeyMode:
      type: string
      enum:
        - live
        - test
      description: >-
        `live` reads and writes your real data; `test` reads and writes your
        sandbox company.
    ErrorDetail:
      type: object
      properties:
        code:
          description: >-
            Machine-readable error type. Branch on this, not on `message`:

            - `validation_failed` (400): a parameter, cursor or body field is
            invalid.

            - `unauthorized` (401): the API key is missing, unknown, revoked or
            expired.

            - `forbidden` (403): the key does not have the scope this endpoint
            requires.

            - `not_found` (404): the resource does not exist in your company.

            - `conflict` (409): the request clashes with work in progress, such
            as another roster sync.

            - `length_required` (411): the request body was sent without a
            `Content-Length` header.

            - `payload_too_large` (413): the request body is larger than the
            endpoint accepts.

            - `rate_limit_exceeded` (429): the key made too many requests; wait
            for `Retry-After` seconds.

            - `bad_request` (other 4xx): the request could not be accepted as
            sent.

            - `internal_error` (500): something failed on our side; contact
            support with the `request_id`.
          example: validation_failed
          allOf:
            - $ref: '#/components/schemas/ErrorCode'
        message:
          type: string
          description: >-
            Human-readable explanation for developers. It may change; do not
            parse it.
          example: limit must not be greater than 100
        request_id:
          type: string
          description: >-
            Unique id of the request, also sent as the `X-Request-Id` header.
            Quote it when you contact support.
          example: req_7Hq2LmX9vT4kPz1RbN8sWc
      required:
        - code
        - message
        - request_id
    ErrorCode:
      type: string
      enum:
        - bad_request
        - validation_failed
        - unauthorized
        - forbidden
        - not_found
        - conflict
        - length_required
        - payload_too_large
        - rate_limit_exceeded
        - internal_error
      description: >-
        Machine-readable error type. Branch on this, not on `message`:

        - `validation_failed` (400): a parameter, cursor or body field is
        invalid.

        - `unauthorized` (401): the API key is missing, unknown, revoked or
        expired.

        - `forbidden` (403): the key does not have the scope this endpoint
        requires.

        - `not_found` (404): the resource does not exist in your company.

        - `conflict` (409): the request clashes with work in progress, such as
        another roster sync.

        - `length_required` (411): the request body was sent without a
        `Content-Length` header.

        - `payload_too_large` (413): the request body is larger than the
        endpoint accepts.

        - `rate_limit_exceeded` (429): the key made too many requests; wait for
        `Retry-After` seconds.

        - `bad_request` (other 4xx): the request could not be accepted as sent.

        - `internal_error` (500): something failed on our side; contact support
        with the `request_id`.
  securitySchemes:
    api-key:
      scheme: bearer
      bearerFormat: API key
      type: http
      description: API key — `tb_live_…` for production data, `tb_test_…` for the sandbox.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.