Skip to content

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 ​

  1. Open the dashboard → Settings → API Keys
  2. Click Create key, give it a label (e.g. "Production backend")
  3. 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:

http
Authorization: Bearer sk_4b737840408f5d3edc79c76268afe9e1...
typescript
const socifyr = new Socifyr({
  apiKey: process.env.SOCIFYR_API_KEY!,
  workspaceId: process.env.SOCIFYR_WORKSPACE_ID!,
})
bash
# Persistent
socifyr configure --key sk_... --workspace <workspaceId>

# Or per-command via env vars
SOCIFYR_API_KEY=sk_... SOCIFYR_WORKSPACE_ID=... socifyr connections
bash
curl -H "Authorization: Bearer sk_..." \
     -H "X-Workspace-Id: <workspaceId>" \
     https://api.socifyr.com/api/content

Rotation ​

To rotate a key:

  1. Create a new key
  2. Deploy with the new key
  3. 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 ​

typescript
// 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:

GuardrailEffect
dailyPostLimitMax 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.
monthlyXSpendCentsCapX (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.
requireApprovalPosts 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, including xSpendCents / xSpendMonth (reserved estimate) so agents can self-audit before hitting a wall
  • A rejected approval (post.reject) returns the post to draft; 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().