> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.trygrant.com/api-reference/authentication/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.trygrant.com/_mcp/server. # Authentication All Grant API endpoints (except the health check) require authentication via an API key sent as a Bearer token in the `Authorization` header. ## Obtaining an API key API keys are created from the [Grant dashboard](https://www.trygrant.com/dashboard). Each key is scoped to a single company and has one of two modes: | Mode | Prefix | Purpose | | -------- | ---------- | --------------------------------------------------- | | **Live** | `ak_live_` | Production traffic and real billing data | | **Test** | `ak_test_` | Development and testing without affecting live data | ## Making authenticated requests Include your API key in the `Authorization` header of every request: ```bash curl https://api.trygrant.com/v1/customers \ -H "Authorization: Bearer ak_live_YOUR_API_KEY" ``` ## Error responses The API returns specific error codes for authentication failures: ### Missing or malformed header Returned when the `Authorization` header is absent or does not follow the `Bearer ` format. ```json { "success": false, "error": { "code": "UNAUTHORIZED", "message": "Missing or invalid Authorization header" }, "request_id": "req_abc123" } ``` **Status:** `401 Unauthorized` ### Invalid API key format Returned when the token is present but does not match the expected `ak_live_*` or `ak_test_*` pattern. ```json { "success": false, "error": { "code": "INVALID_API_KEY", "message": "Invalid API key format" }, "request_id": "req_abc123" } ``` **Status:** `401 Unauthorized` ### Invalid API key Returned when the token format is valid but the key does not exist. ```json { "success": false, "error": { "code": "INVALID_API_KEY", "message": "Invalid API key" }, "request_id": "req_abc123" } ``` **Status:** `401 Unauthorized` ### Revoked API key Returned when the API key has been revoked from the dashboard. ```json { "success": false, "error": { "code": "API_KEY_REVOKED", "message": "API key has been revoked" }, "request_id": "req_abc123" } ``` **Status:** `401 Unauthorized` ### Service unavailable Returned when the authentication service cannot reach the database. Retry with exponential backoff. ```json { "success": false, "error": { "code": "SERVICE_UNAVAILABLE", "message": "Authentication service unavailable" }, "request_id": "req_abc123" } ``` **Status:** `503 Service Unavailable` ## Rate limiting Authenticated requests are subject to rate limits of 1,000 requests per 60-second window per company. Rate limit status is communicated via response headers: | Header | Description | | ----------------------- | --------------------------------------------- | | `X-RateLimit-Limit` | Maximum requests allowed per window | | `X-RateLimit-Remaining` | Requests remaining in the current window | | `X-RateLimit-Reset` | Unix timestamp when the current window resets | When the limit is exceeded, the API returns a `429 Too Many Requests` response. ## Security best practices > **Note** > > Never expose API keys in client-side code, public repositories, or browser requests. Always send API calls from your server. * **Rotate keys regularly** — Generate new keys and revoke old ones from the dashboard. * **Use test keys for development** — Keep `ak_test_` keys for staging and local development. Use `ak_live_` keys only in production. * **Store keys securely** — Use environment variables or a secrets manager. Never commit keys to source control. * **Monitor usage** — Check the dashboard for unexpected spikes in API usage that may indicate a compromised key. > API documentation for Grant — billing infrastructure for usage-based pricing