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

# Exchange challenge for token

> Exchange a signed challenge for a short-lived wallet-bound JWT.

Public endpoint. No JWT or `Authorization` header is required. It verifies the wallet's signed challenge, consumes the challenge, and returns a wallet-bound bearer token. A challenge succeeds at most once.

<ParamField body="challengeId" type="string" required>
  Lowercase 32-character challenge ID returned by `POST /auth/challenge`.
</ParamField>

<ParamField body="signature" type="string" required>
  Canonical low-s, 65-byte EOA personal-sign signature. The recovery byte may be `0`/`1` or `27`/`28`.
</ParamField>

<RequestExample>
  ```curl cURL theme={null}
  curl --request POST \
    --url https://relay.mainnet.kuru.io/auth/token \
    --header 'Content-Type: application/json' \
    --data '{"challengeId":"8c4a11c6eb574d16972fac2a8c85a6dc","signature":"0x<65-byte-signature>"}'
  ```
</RequestExample>

<ResponseField name="accessToken" type="string" required>
  Short-lived wallet-bound JWT. Treat it as a secret and never log it.
</ResponseField>

<ResponseField name="tokenType" type="string" required>
  Always `Bearer`.
</ResponseField>

<ResponseField name="expiresAt" type="string" required>
  Token expiration as an ISO 8601 timestamp. Testnet tokens last one hour.
</ResponseField>

<ResponseField name="wallet" type="string" required>
  Address to which the JWT is bound.
</ResponseField>

<ResponseExample>
  ```json 200 theme={null}
  {
    "accessToken": "eyJhbGciOiJIUzI1NiIs...",
    "tokenType": "Bearer",
    "expiresAt": "2026-08-27T11:00:00Z",
    "wallet": "0x1111111111111111111111111111111111111111"
  }
  ```

  ```json 401 theme={null}
  {
    "code": "AUTHENTICATION_FAILED",
    "message": "authentication failed",
    "retryable": false
  }
  ```
</ResponseExample>


## OpenAPI

````yaml api/relay/openapi.yaml POST /auth/token
openapi: 3.1.0
info:
  title: Kuru Relay API
  version: 1.0.0
servers:
  - url: https://relay.mainnet.kuru.io
    description: Monad mainnet (default; submits real transactions)
  - url: https://relay.testnet.kuru.io
    description: Monad testnet
security: []
paths:
  /auth/token:
    post:
      summary: Exchange signed challenge for JWT
      operationId: exchangeToken
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - challengeId
                - signature
              properties:
                challengeId:
                  type: string
                signature:
                  type: string
      responses:
        '200':
          description: Wallet-bound JWT
      security: []

````

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