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

# Create an access token

> Exchange your client id and secret for a one-hour bearer token. Server-side only.



## OpenAPI

````yaml api-reference/v1/openapi.json POST /oauth/token
openapi: 3.1.0
info:
  title: Laces Partner API
  version: 1.0.0
  summary: Show your organization's races and sell entries from your own website.
  description: >-
    The Laces Partner API, served at `https://connect.laces.run/v1`. Every path
    is relative to that server URL, which already ends in `/v1`.


    Authenticate with a **bearer token** from `POST /oauth/token` (server side)
    or, on the routes that allow it, a **publishable key** in
    `X-Laces-Publishable-Key` (browser side, from an allowed domain). Keys are
    uppercase and case-sensitive: send them exactly as issued.


    There is one environment, production. Payments made through the API are
    real.


    Money is integer minor units. Every route except the token endpoint answers
    in the Laces envelope `{ code, message, data | error, error_code }`; branch
    on `error_code`, never on `message` or `error`.


    Every response carries an `X-Request-Id` header (`req_…`). Quote it to
    support@laces.run when something goes wrong. Browsers can read
    `X-Request-Id` and `Retry-After` (both are CORS-exposed). Rate-limited
    routes also send the standard `RateLimit-Limit`, `RateLimit-Remaining` and
    `RateLimit-Reset` headers.


    Partner credentials are accepted on this host only. Sent to `api.laces.run`
    (the Laces app's own API), any partner credential is refused with `401
    partner_credential_not_accepted`.
  contact:
    name: Laces support
    email: support@laces.run
    url: https://docs.laces.run
  license:
    name: Proprietary
    identifier: LicenseRef-Proprietary
servers:
  - url: https://connect.laces.run/v1
    description: Production
security:
  - bearerAuth: []
tags:
  - name: Authentication
    description: OAuth 2.0 client credentials.
  - name: Events
    description: Your organization's races that are on sale.
  - name: Checkout sessions
    description: 'Laces-hosted checkout: redirect or embedded.'
  - name: Orders
    description: Create, pay and read orders from your own UI.
  - name: Webhook events
    description: Requests Laces sends to your webhook endpoint.
  - name: Health
    description: Liveness probe.
paths:
  /oauth/token:
    post:
      tags:
        - Authentication
      summary: Create an access token
      description: >-
        OAuth 2.0 client credentials grant (RFC 6749 §4.4). Exchange your client
        id and secret for a bearer token valid for **3600 seconds**.


        Send `application/x-www-form-urlencoded` (or JSON). Authenticate with
        HTTP Basic **or** with `client_id` and `client_secret` in the body,
        never both. `scope` is optional: omit it to get every scope the client
        holds, or ask for a subset.


        **Server-to-server only.** A request carrying an `Origin` header is
        refused with `400 invalid_request`, and no CORS headers are sent, so
        this endpoint cannot be called from a browser. Cache the token for its
        hour: this endpoint allows about 10 requests a minute per client id and
        IP.


        Responses use the bare OAuth shape (`access_token`… or `error`,
        `error_description`), not the Laces envelope.


        **In the playground** you are sending a real, live client secret through
        the docs proxy. Prefer curl from your own machine.
      operationId: createAccessToken
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/TokenRequest'
            example:
              grant_type: client_credentials
              scope: events:read orders:write
          application/json:
            schema:
              $ref: '#/components/schemas/TokenRequest'
            example:
              grant_type: client_credentials
              client_id: LCSCLI-EXAMPLECLNT2345EXAMP
              client_secret: LCSSECK-EXAMPLESECRET2345678EXAMPLESECRET2345678EXAMPLESECRE-X
      responses:
        '200':
          description: 'A bearer token. `Cache-Control: no-store`.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TokenResponse'
              example:
                access_token: LCSTOK-EXAMPLETKN23456789EXAMPLETKN23456789EXAMPLETKN234567-X
                token_type: Bearer
                expires_in: 3600
                scope: events:read orders:write checkout_sessions:write
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
        '400':
          description: >-
            Bad request: an `Origin` header present, `grant_type` missing, two
            authentication methods, a body that could not be parsed or is over
            10 kB, or a scope the client does not hold.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OAuthError'
              examples:
                invalid_request:
                  summary: >-
                    Origin header present, grant_type missing, or two auth
                    methods
                  value:
                    error: invalid_request
                    error_description: >-
                      The token endpoint is server to server only and must not
                      be called from a browser
                unsupported_grant_type:
                  value:
                    error: unsupported_grant_type
                    error_description: Only client_credentials is supported
                invalid_scope:
                  value:
                    error: invalid_scope
                    error_description: Requested scope exceeds the scopes granted to this client
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
        '401':
          description: >-
            Unknown client id, wrong or expired secret, or a revoked client.
            Comes with `WWW-Authenticate: Basic`. The client id and secret are
            case-sensitive.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OAuthError'
              example:
                error: invalid_client
                error_description: Client authentication failed
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
        '429':
          description: >-
            Too many token requests. `temporarily_unavailable` (RFC 6749
            §4.1.2.1) tells an OAuth library to back off; wait `Retry-After`
            seconds. Reuse tokens instead of requesting one per call.
          headers:
            Retry-After:
              description: Whole seconds until you may retry.
              schema:
                type: integer
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OAuthError'
              example:
                error: temporarily_unavailable
                error_description: >-
                  Too many token requests. Retry after the number of seconds in
                  the Retry-After header.
        '500':
          description: Unexpected failure.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OAuthError'
              example:
                error: server_error
                error_description: Could not issue a token
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
      security:
        - clientBasic: []
        - {}
components:
  schemas:
    TokenRequest:
      type: object
      properties:
        grant_type:
          type: string
          enum:
            - client_credentials
        scope:
          type: string
          description: Space-separated. Omit to get every scope the client holds.
          examples:
            - events:read orders:write
        client_id:
          type: string
          description: Body authentication only (instead of Basic).
          examples:
            - LCSCLI-EXAMPLECLNT2345EXAMP
        client_secret:
          type: string
          description: Body authentication only (instead of Basic). Server-side only.
          examples:
            - LCSSECK-EXAMPLESECRET2345678EXAMPLESECRET2345678EXAMPLESECRE-X
      required:
        - grant_type
    TokenResponse:
      type: object
      properties:
        access_token:
          type: string
          examples:
            - LCSTOK-EXAMPLETKN23456789EXAMPLETKN23456789EXAMPLETKN234567-X
        token_type:
          type: string
          enum:
            - Bearer
        expires_in:
          type: integer
          examples:
            - 3600
        scope:
          type: string
          description: The granted scopes, space-separated.
      required:
        - access_token
        - token_type
        - expires_in
        - scope
    OAuthError:
      type: object
      properties:
        error:
          type: string
          enum:
            - invalid_request
            - invalid_client
            - unsupported_grant_type
            - invalid_scope
            - temporarily_unavailable
            - server_error
        error_description:
          type: string
      required:
        - error
      description: RFC 6749 §5.2 error. The token endpoint does not use the Laces envelope.
  headers:
    X-Request-Id:
      description: >-
        Unique id of this request (`req_…`). On every response, readable from
        browsers. Quote it to support.
      schema:
        type: string
      example: req_V1StGXR8Z5jdHi6BmyTq
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: LCSTOK-…-X (opaque)
      description: >-
        A token from `POST /oauth/token`, valid 1 hour. Paste it as `LCSTOK-…-X`
        (without the word Bearer).
    clientBasic:
      type: http
      scheme: basic
      description: >-
        Client id as the username, client secret as the password. Token endpoint
        only. These are live credentials: keep the secret on your server.

````

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