Authentication
All API requests require a Bearer token in the Authorization header.
Base URL: https://www.brainpercent.app/api/v1 Always include the www. The apex domain 307-redirects to www, and most HTTP clients drop the request body when they follow a redirect, so a POST to the apex silently arrives with nothing in it.
Bearer Token
Include your API key in the Authorization header with every request:
curl https://www.brainpercent.app/api/v1/articles \
-H "Authorization: Bearer bp_your_api_key_here"Key Format
API keys follow the format: bp_ followed by 64 hexadecimal characters (67 characters total).
Keys are shown only once at creation. The server stores a SHA-256 hash, so a lost key cannot be recovered. Revoke it and create a new one.
Creating API Keys
Create and revoke keys on the Developer Settings page in your dashboard. The key management routes are session-authenticated, meaning they read your signed-in browser cookie, so there is no way to create a key from a script using another key.
A Bearer bp_... header against /api/v1/api-keys does not authenticate. See the API Keys reference for the exact request and response shapes, and note that those routes return a flat { "error": "..." } body instead of the envelope described below.
A key created without an explicit permissions list gets ["read"], and every write endpoint will return 403 for it. You can hold at most 10 active keys.
Error Codes
| Status | Code | Description |
|---|---|---|
| 400 | VALIDATION_ERROR | Request body or query parameters failed validation |
| 400 | NO_PROJECT | The account has no project yet, create one in the app |
| 401 | UNAUTHORIZED | Missing or invalid API key |
| 402 | INSUFFICIENT_CREDITS | Not enough credits for the operation |
| 403 | FORBIDDEN | Key lacks the required permission or scope |
| 404 | NOT_FOUND | Resource does not exist or is not owned by your account |
| 409 | CONFLICT | The resource is already in the target state, for example already published |
| 412 | PRECONDITION_FAILED | The resource is not ready yet, or a required connection is missing |
| 429 | RATE_LIMIT_EXCEEDED | Too many requests. The response also carries Retry-After. |
| 500 | INTERNAL_ERROR | Unexpected server error. Include the request_id when reporting it. |
Every Bearer endpoint returns the same error envelope:
{
"success": false,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Too many requests. Please slow down."
},
"meta": {
"request_id": "req_abc123",
"timestamp": "2026-02-01T00:00:00Z"
}
}Response Headers
Every Bearer response carries these headers:
| Header | Meaning |
|---|---|
| X-Request-Id | Identifier for this request. Quote it in any support report. |
| X-RateLimit-Limit | Requests allowed in the current minute window |
| X-RateLimit-Remaining | Requests left in the current minute window |
| X-RateLimit-Reset | When the minute window resets, as UTC epoch seconds |
| X-RateLimit-Daily-Limit | Daily request allowance. Omitted when the daily limit is unlimited. |
| X-RateLimit-Daily-Remaining | Daily requests left. Omitted when the daily limit is unlimited. |
| Retry-After | Sent on 429 responses only |
Rate Limits
Rate limits are enforced per API key and depend on your plan:
| Plan | Per minute | Per day |
|---|---|---|
| Free | 100 | 5,000 |
| Starter, Plus, Pro, Business | 1,000 | 50,000 |
| Enterprise | 10,000 | unlimited |
Permissions
API keys can be created with specific permissions that control what operations are allowed. The default is ["read"]:
| Permission | HTTP Methods | Description |
|---|---|---|
read | GET | List and retrieve resources: articles, social content, projects, credits, usage |
write | POST | Create and modify resources: generate articles, generate social content, publish |
delete | DELETE | Remove resources. None of the Bearer endpoints documented here require it, and revoking a key is session-authenticated. |
Scopes
Scopes restrict which resource types an API key can access:
| Scope | Endpoints |
|---|---|
articles | /api/v1/articles/*, /api/v1/articles/generate, /api/v1/articles/:id/status |
social | /api/v1/social/content/*, /api/v1/social/generate, /api/v1/social/publish |
projects | /api/v1/projects/* |
user | /api/v1/user/credits, /api/v1/user/usage |
A request is authorized only when the API key has both the required permission AND the matching scope. For example, generating an article requires the write permission and the articles scope.
Key Rotation
Best practices for rotating API keys:
- Create a new key with the same permissions and scopes before revoking the old one
- Update your application configuration to use the new key
- Verify the new key works by making a test request
- Revoke the old key from Developer Settings, revocation is session-authenticated and cannot be scripted with an API key
- Set key expiration (
expires_in_days) to enforce periodic rotation - Use separate keys for different environments (development, staging, production)
CORS
Cross-Origin Resource Sharing (CORS) is configured for the API:
| Header | Value |
|---|---|
| Access-Control-Allow-Origin | * (all origins) |
| Access-Control-Allow-Methods | GET, POST, PUT, DELETE, OPTIONS |
| Access-Control-Allow-Headers | Authorization, Content-Type, X-Request-Id |
| Access-Control-Max-Age | 86400 (24 hours) |
While CORS allows browser-based requests, avoid exposing your API key in client-side code. Use a backend proxy or serverless function to keep your key secure.