Authentication
How to authenticate with the FeedHorizon API using API keys.
Overview
All FeedHorizon API requests must include a valid API key in the Authorization header using the Bearer scheme.
Authorization: Bearer fh_YOUR_API_KEYAPI key format
Keys follow this format:
| Part | Description |
|---|---|
fh_ | Fixed prefix identifying FeedHorizon keys |
| 64 hex characters | Random cryptographic payload |
Total length: 67 characters (e.g. fh_aee6d4242ae1d2ff857b4a900904f9e5beac1f2168a6c83da9f63053fda8caf8)
Keys are hashed with SHA-256 before storage. The plaintext key is only shown once at creation.
Scopes
Each key carries a list of scopes. A scope names a resource and an access level, for example posts:write. A :write scope includes :read for the same resource.
| Resource | Scopes |
|---|---|
| Profiles | profiles:read, profiles:write |
| Social accounts | accounts:read, accounts:write |
| Posts | posts:read, posts:write |
| Webhooks | webhooks:read, webhooks:write |
| API keys | api_keys:read, api_keys:write |
| Platform invites | platform_invites:read, platform_invites:write |
A call without the needed scope answers 403 insufficient_scope. GET /api/v1/me and GET /api/v1/platforms work with any valid key; /me shows the scopes of the key you are using.
The permission field is a shorthand when you create a key: readwrite grants every scope, readonly every :read scope. If you send scopes, they win over permission. Keys created before scopes existed kept exactly what they could do.
Profile scope
Keys can be scoped to specific profiles:
- Full access — Can access all profiles (including future ones)
- Specific profiles — Only access posts and accounts belonging to the selected profiles
Objects in profiles the key cannot access answer 404, as if they did not exist. Creating profiles and managing API keys needs a key with full access; other keys get 403 all_profiles_required.
Key management
Create a key
curl -X POST https://feedhorizon.com/api/v1/api-keys \
-H "Authorization: Bearer fh_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "CI/CD Pipeline", "permission": "readwrite" }'A key that may only schedule posts:
curl -X POST https://feedhorizon.com/api/v1/api-keys \
-H "Authorization: Bearer fh_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "Scheduler", "scopes": ["posts:write", "profiles:read"] }'The response includes the full key field — store it immediately, it won't be shown again.
List keys
curl https://feedhorizon.com/api/v1/api-keys \
-H "Authorization: Bearer fh_YOUR_API_KEY"Returns key metadata with keyPrefix only (e.g. fh_abc12345).
Delete a key
curl -X DELETE https://feedhorizon.com/api/v1/api-keys/KEY_ID \
-H "Authorization: Bearer fh_YOUR_API_KEY"Deletion is immediate and irreversible.
Expiring keys
Set expiresAt when creating a key to automatically expire it:
{
"name": "Temp key",
"expiresAt": "2026-12-31T23:59:59Z"
}An expired key answers 401 with the code invalid_api_key, the same as a revoked or unknown key.
Authentication errors
| Status | Code | Meaning |
|---|---|---|
| 401 | missing_api_key | No Authorization: Bearer header |
| 401 | invalid_api_key | Unknown, revoked or expired key |
| 403 | insufficient_scope | The key lacks the scope for this endpoint |
| 403 | all_profiles_required | The endpoint needs a key with full access |
See Error handling for the error format.
Security best practices
- Never commit keys to source control — Use environment variables
- Use read-only keys when you only need to fetch data
- Scope keys to specific profiles to limit blast radius
- Set expiry dates for temporary integrations
- Rotate keys regularly — Delete old keys and create new ones
- Monitor
lastUsedAtin the dashboard to detect unused keys