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

# Obtain access token

> POST /oauth2/token — OAuth 2.0 client credentials

## Endpoint

```http theme={null}
POST https://api.routera.io/oauth2/token
```

**Route:** `/oauth2/token`\
**Content-Type:** `application/x-www-form-urlencoded`

<Note>
  This endpoint does **not** return a refresh token. When `expires_in` elapses, call this endpoint again with the same client credentials.
</Note>

## Request body

All parameters are sent as **form fields** (`application/x-www-form-urlencoded`). `client_id` and `client_secret` are **required**.

| Parameter       | Required | Description                  |
| --------------- | -------- | ---------------------------- |
| `grant_type`    | Yes      | Must be `client_credentials` |
| `client_id`     | Yes      | Your API client id           |
| `client_secret` | Yes      | Your API client secret       |

### Example

```bash theme={null}
curl -X POST 'https://api.routera.io/oauth2/token' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET'
```

### Alternative: HTTP Basic

You may also send credentials in the `Authorization` header instead of the form body:

```http theme={null}
Authorization: Basic base64(client_id:client_secret)
```

When using Basic auth, the body still requires `grant_type=client_credentials`.

## Response

**200** — Token issued

```json theme={null}
{
  "access_token": "eyJraWQiOi...",
  "expires_in": 3600,
  "token_type": "Bearer"
}
```

Use `access_token` on subsequent requests:

```http theme={null}
Authorization: Bearer eyJraWQiOi...
```

## Errors

| Status | When                                   |
| ------ | -------------------------------------- |
| `400`  | Missing or invalid `grant_type`        |
| `401`  | Invalid `client_id` or `client_secret` |

Error responses follow the standard OAuth 2.0 format (`error`, `error_description`).

## Next step

After obtaining a token, see [API introduction](/api-reference/introduction) for object routes and response format.


## OpenAPI

````yaml POST /oauth2/token
openapi: 3.0.1
info:
  title: Routera API
  description: >-
    Routera v2 REST API. Objects CRUD for contacts, companies, deals, and
    tickets, routers read API, plus router dispatch.
  version: 1.0.0
servers:
  - url: https://api.routera.io
    description: >-
      API Gateway base URL (override with ROUTERA_API_BASE_URL when generating
      docs)
security: []
tags:
  - name: Authentication
    description: Access token issuance
  - name: Contacts
    description: Contact records
  - name: Companies
    description: Company records
  - name: Deals
    description: Deal records
  - name: Tickets
    description: Ticket records
  - name: Routers
    description: Router configuration
  - name: Dispatch
    description: Router assignment
paths:
  /oauth2/token:
    post:
      tags:
        - Authentication
      summary: Obtain access token
      description: >-
        OAuth 2.0 client credentials token endpoint. Send grant_type, client_id,
        and client_secret as form fields.
      operationId: oauth2Token
      requestBody:
        $ref: '#/components/requestBodies/OAuthTokenBody'
      responses:
        '200':
          description: Access token issued
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OAuthTokenResponse'
        '400':
          description: Invalid or missing grant_type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
        '401':
          description: Invalid client credentials
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
      security: []
components:
  requestBodies:
    OAuthTokenBody:
      required: true
      description: >-
        Requires grant_type, client_id, and client_secret as
        application/x-www-form-urlencoded fields.
      content:
        application/x-www-form-urlencoded:
          schema:
            $ref: '#/components/schemas/OAuthTokenRequest'
          example:
            grant_type: client_credentials
            client_id: your-client-id
            client_secret: your-client-secret
  schemas:
    OAuthTokenResponse:
      type: object
      required:
        - access_token
        - expires_in
        - token_type
      properties:
        access_token:
          type: string
          description: 'JWT access token — use as `Authorization: Bearer` on API routes'
        expires_in:
          type: integer
          description: Token lifetime in seconds
        token_type:
          type: string
          enum:
            - Bearer
    ApiError:
      type: object
      required:
        - message
        - error
      properties:
        message:
          type: string
        error:
          type: boolean
          enum:
            - true
        field:
          type: string
          description: Field that caused a conflict (409 duplicate responses)
    OAuthTokenRequest:
      type: object
      required:
        - grant_type
        - client_id
        - client_secret
      properties:
        grant_type:
          type: string
          enum:
            - client_credentials
          default: client_credentials
          description: Must be `client_credentials`
        client_id:
          type: string
          description: API client id (required)
          example: your-client-id
          x-default: your-client-id
        client_secret:
          type: string
          format: password
          description: API client secret (required)
          example: your-client-secret
          x-default: your-client-secret
      example:
        grant_type: client_credentials
        client_id: your-client-id
        client_secret: your-client-secret

````