> For the complete documentation index, see [llms.txt](https://boundaryai.gitbook.io/boundaryai-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://boundaryai.gitbook.io/boundaryai-docs/api-and-webhooks/api-keys.md).

# API Keys

Introspect the calling key: its permissions, effective rate limits, credit status, and the webhook events available for subscription.

## Self-serve info about the calling API key

> Returns the key's own public fields (name, environment, permissions), the effective rate limits, the org's credit status, and the webhook event types available for subscriptions — so an integration can introspect its own capabilities without dashboard access.\
> \
> \*\*Response envelope migration:\*\* during the current migration window, 2xx responses carry the bare payload shown in the example (the value of the schema's \`data\` property, without the \`{"data": ...}\` wrapper). The \`Deprecation\` and \`Sunset\` headers on every 2xx announce this envelope migration — they do \*\*not\*\* deprecate the endpoint itself. After the \`Sunset\` date, responses will be wrapped as \`{"data": ...}\` exactly as the schema declares.

```json
{"openapi":"3.1.0","info":{"title":"BAI Analytics API","version":"1.3.0"},"tags":[{"name":"API keys","description":"Introspect the calling key: its permissions, effective rate limits, credit status, and the webhook events available for subscription."}],"servers":[{"url":"https://app.boundary-ai.com","description":"Production"}],"security":[{"apiKeyAuth":[]}],"components":{"securitySchemes":{"apiKeyAuth":{"type":"http","scheme":"bearer","bearerFormat":"BAI Analytics API key","description":"API key authentication: pass your key in the Authorization header as `Bearer inpk_live_...` (or `inpk_test_...` for a test-environment key). Create and manage keys in the dashboard under Integrations Hub -> API Keys. Each key carries a permission scope (push, create, send, mcp_read, or all) and a per-minute rate limit."}},"schemas":{"KeySelfInfoResponse":{"description":"GET /api/input/me — what the calling key can see about itself.","properties":{"key":{"additionalProperties":true,"description":"Public key fields (id, name, environment, permissions, …)","title":"Key","type":"object"},"org_id":{"title":"Org Id","type":"integer"},"rate_limits":{"$ref":"#/components/schemas/KeyRateLimits"},"credits":{"anyOf":[{"$ref":"#/components/schemas/KeyCreditsStatus"},{"type":"null"}],"default":null,"description":"APS credit status for the key's org"},"webhook_events":{"description":"Event types available for webhook subscriptions","items":{"type":"string"},"title":"Webhook Events","type":"array"}},"required":["key","org_id","rate_limits"],"title":"KeySelfInfoResponse","type":"object"},"KeyRateLimits":{"properties":{"per_key_per_minute":{"title":"Per Key Per Minute","type":"integer"},"per_org_per_minute":{"title":"Per Org Per Minute","type":"integer"},"per_ip_per_minute":{"title":"Per Ip Per Minute","type":"integer"},"window_seconds":{"title":"Window Seconds","type":"integer"}},"required":["per_key_per_minute","per_org_per_minute","per_ip_per_minute","window_seconds"],"title":"KeyRateLimits","type":"object"},"KeyCreditsStatus":{"additionalProperties":true,"description":"APS credit status of the calling key's org, as returned by\n``GET /api/input/me``. Extra keys may be added over time.","properties":{"plan_key":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Deprecated — plans no longer exist; always absent","title":"Plan Key"},"limit":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"APS quota for the current billing period","title":"Limit"},"used":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"APS consumed this period (fractional under token billing)","title":"Used"},"remaining":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"APS remaining this period","title":"Remaining"},"period_start":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"ISO-8601 period start, null on the free plan","title":"Period Start"},"period_end":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"ISO-8601 period end, null on the free plan","title":"Period End"},"rate_tokens_per_aps":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"Live token-to-APS conversion rate","title":"Rate Tokens Per Aps"}},"title":"KeyCreditsStatus","type":"object"},"ErrorEnvelope":{"description":"Top-level error response.\n\nSchema name in the OpenAPI document: ``ErrorEnvelope``.","properties":{"error":{"$ref":"#/components/schemas/ErrorObject"},"details":{"anyOf":[{},{"type":"null"}],"default":null,"description":"Optional structured details (e.g. validation field map)","title":"Details"}},"required":["error"],"title":"ErrorEnvelope","type":"object"},"ErrorObject":{"description":"The inner ``error`` field of an error envelope.\n\nSchema name in the OpenAPI document: ``ErrorObject``.","properties":{"code":{"description":"Machine-readable error code drawn from ErrorCode enum","title":"Code","type":"string"},"message":{"description":"Human-readable error message, safe to display","title":"Message","type":"string"}},"required":["code","message"],"title":"ErrorObject","type":"object"}},"responses":{"RateLimited":{"description":"Rate limit exceeded — see Retry-After header.","headers":{"Retry-After":{"$ref":"#/components/headers/RetryAfter"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"headers":{"RetryAfter":{"description":"Seconds to wait before retrying. Emitted on 429 responses and on 503 responses from the global rate limiter. Rate-limit windows are fixed (anchored at the first request in the window): requests rejected with 429 do not extend the window, so waiting until ``X-RateLimit-Reset`` always recovers.","schema":{"type":"integer","minimum":1}},"XRateLimitLimit":{"description":"Total requests allowed in the current rate-limit window.","schema":{"type":"integer","minimum":1}},"XRateLimitRemaining":{"description":"Requests remaining in the current rate-limit window.","schema":{"type":"integer","minimum":0}},"XRateLimitReset":{"description":"Unix timestamp when the rate-limit window resets. The window is fixed from its first request — 429-rejected requests do not push this forward.","schema":{"type":"integer","minimum":0}}}},"paths":{"/api/input/me":{"get":{"summary":"Self-serve info about the calling API key","description":"Returns the key's own public fields (name, environment, permissions), the effective rate limits, the org's credit status, and the webhook event types available for subscriptions — so an integration can introspect its own capabilities without dashboard access.\n\n**Response envelope migration:** during the current migration window, 2xx responses carry the bare payload shown in the example (the value of the schema's `data` property, without the `{\"data\": ...}` wrapper). The `Deprecation` and `Sunset` headers on every 2xx announce this envelope migration — they do **not** deprecate the endpoint itself. After the `Sunset` date, responses will be wrapped as `{\"data\": ...}` exactly as the schema declares.","tags":["API keys"],"operationId":"inputapi_get_me","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/KeySelfInfoResponse"}},"required":["data"]}}}},"401":{"description":"Unauthorized — missing or invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}}}}
```
