API keys
Every Socifyr API call is authenticated with an API key. Keys are scoped to a workspace and inherit the role of whoever created them.
Creating a key
- Open the dashboard → Settings → API Keys
- Click Create key, give it a label (e.g. "Production backend")
- Copy the key starting with
sk_— shown only once
Keys are stored hashed; if you lose one, create a new one and delete the old.
Using a key
Send it in the Authorization header as a Bearer token:
Authorization: Bearer sk_4b737840408f5d3edc79c76268afe9e1...const socifyr = new Socifyr({
apiKey: process.env.SOCIFYR_API_KEY!,
workspaceId: process.env.SOCIFYR_WORKSPACE_ID!,
})# Persistent
socifyr configure --key sk_... --workspace <workspaceId>
# Or per-command via env vars
SOCIFYR_API_KEY=sk_... SOCIFYR_WORKSPACE_ID=... socifyr connectionscurl -H "Authorization: Bearer sk_..." \
-H "X-Workspace-Id: <workspaceId>" \
https://api.socifyr.com/api/contentRotation
To rotate a key:
- Create a new key
- Deploy with the new key
- Delete the old key from the dashboard
There's no downtime — both keys are valid in parallel until you delete the old one.
Managing keys via the API
// List
const keys = await socifyr.workspaces.listApiKeys(workspaceId)
// Create
const { key } = await socifyr.workspaces.createApiKey(workspaceId, {
label: 'CI bot',
})
console.log(key) // sk_... — only returned once
// Update guardrails (needs a dashboard session or an unrestricted key —
// a key that has guardrails cannot manage API keys)
await socifyr.workspaces.updateApiKey(workspaceId, keyId, {
dailyPostLimit: 50,
monthlyXSpendCentsCap: 1500, // US cents — $15.00/month of X spend
requireApproval: true,
})
// Delete
await socifyr.workspaces.deleteApiKey(workspaceId, keyId)Agent guardrails
Autonomous agents make mistakes at machine speed. Every API key supports optional guardrails that apply only to posts created through that key — the dashboard and human-published content are never affected. Set them in the dashboard (API Keys → shield icon) or via updateApiKey:
| Guardrail | Effect |
|---|---|
dailyPostLimit | Max posts dispatched per UTC day through this key. A post counts once, when it leaves draft (created without saveDraft, published, or submitted for approval). Deleting a post does not give the slot back. Requests beyond the limit fail with 403. Resets at 00:00 UTC. null = unlimited. |
monthlyXSpendCentsCap | X (Twitter) charges per post (~$0.015, $0.20 with a link). Each X post is reserved against the key's monthly budget at the moment it is dispatched — including scheduled and bulk-scheduled posts — so the cap can never be overshot. Posts that would exceed it fail with 403. Resets monthly. null = unlimited. |
requireApproval | Posts created with this key land in pending_approval instead of publishing. A teammate with post.approve permission reviews them in the dashboard — approving pushes the post out unchanged. |
What a guarded key can and cannot do
A key with any guardrail set is restricted so it cannot be used to get around its own limits:
- Allowed: create posts (text, photos, video, document, bulk-schedule), read posts/status/analytics/usage, upload and read media, list connections, AI caption helpers — and edit, publish, retry, archive, delete or submit only posts it created itself.
- Edits are drafts-only: once a post is submitted, approved or scheduled, the key can no longer change it.
- requireApproval keys can only submit drafts for approval (
POST /content/:id/submit-for-approval) — they get 403 on publish, publish-now, approve and reject. - Everything else is denied (403): managing API keys (including its own guardrails), members and invitations, webhooks, workspace settings, connections, approvals, billing. Change guardrails from the dashboard or with an unrestricted key.
- Limits are enforced atomically, so parallel requests cannot push a key past them.
Behavior notes:
- Drafts reserve nothing until they leave draft; a rejected post that is edited and resubmitted only reserves the difference (e.g. an X channel added)
- Guardrail fields appear on each key in
listApiKeys()responses, includingxSpendCents/xSpendMonth(reserved estimate) so agents can self-audit before hitting a wall - A rejected approval (
post.reject) returns the post todraft; it never publishes
Security tips
- Never commit a key to source control. Use environment variables or a secrets manager
- Don't ship API keys in client-side code (mobile apps, browser bundles)
- Do create separate keys per service (frontend, CI, scripts) so you can rotate one without disturbing the rest
- Do delete keys for departed teammates immediately
Last-used tracking
Every authenticated request updates the key's lastUsedAt timestamp. You can audit unused keys via workspaces.listApiKeys().