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

# Request API Key Challenge

> Step 1 of the API key mint flow. Returns a nonce message that the partner wallet must sign.

## Overview

Starts the challenge-response flow used to mint a partner API key. Submit the partner wallet address and partner ID; GRAIL returns a short-lived nonce message that must be signed with the partner wallet's private key and exchanged via [Create API Key](/api-reference/authentication/create-api-key).

<Warning>
  The challenge expires **2 minutes** after it is issued. Complete the signing and exchange before then.
</Warning>

<Note>
  This endpoint is **rate-limited to 10 requests per minute per IP**. Exceeding the limit returns `429 rate_limited`.
</Note>

## Request Body

<ParamField body="wallet_address" type="string" required>
  The partner wallet address requesting the key. Must be an active wallet registered under the given partner.
</ParamField>

<ParamField body="partner_id" type="string" required>
  The partner ID (UUID) the wallet belongs to. Provided by ORO when your partner is onboarded.
</ParamField>

## Response

<ResponseField name="challenge_id" type="string">
  Unique identifier for this challenge, prefixed `ch_`. Embedded in the `message`.
</ResponseField>

<ResponseField name="message" type="string">
  The exact message to sign with the partner wallet. Format: `Sign this message to generate an API key for GRAIL: ch_<uuid>`.
</ResponseField>

<ResponseField name="expires_at" type="string">
  ISO-8601 timestamp. The challenge is unusable after this time.
</ResponseField>

## Errors

| HTTP | `error`            | When                                                                      |
| ---- | ------------------ | ------------------------------------------------------------------------- |
| 400  | `invalid_request`  | Missing `wallet_address` or `partner_id`                                  |
| 400  | `invalid_wallet`   | `wallet_address` is not a valid Solana pubkey                             |
| 404  | `wallet_not_found` | The wallet is not registered under this partner, or its status is revoked |
| 429  | `rate_limited`     | More than 10 requests in the last minute from this IP                     |

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST https://grail-stack-dev.onrender.com/v1/auth/challenge \
    -H "Content-Type: application/json" \
    -d '{
      "wallet_address": "Fd31QxW7RRZwvMfNnhNaPvczJpMh7wyzBTWvtMA66wjN",
      "partner_id": "d8a8df53-36ca-4f4d-96ef-cf0a49d51e5d"
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json 200 OK theme={null}
  {
    "challenge_id": "ch_9b5a3a12-7b89-4d6c-9f6a-18c52d3f9e3a",
    "message": "Sign this message to generate an API key for GRAIL: ch_9b5a3a12-7b89-4d6c-9f6a-18c52d3f9e3a",
    "expires_at": "2026-04-19T12:32:00.000Z"
  }
  ```
</ResponseExample>
