Authenticating with API keys

Generate an API key, scope it to the resources your integration needs, and call the Journalify REST API.

5 min read

Generate an API key

Sign in to your Journalify newsroom, open the Webhooks page, and switch to the API Keys tab. Click "Create key", give it a descriptive name (e.g. "Mailchimp digest"), pick the scopes the integration needs, and optionally set an expiry. The full secret is shown once at creation time — copy it into your secret manager immediately.

Treat API keys like passwords. Never commit them to source control, never paste them into chat tools, and never embed them in frontend code.

Key format

API keys look like this:

jnf_abc12345_yourSecretHere

The 8-character prefix after jnf_ is the public key ID — it shows up in audit logs and error messages so you can identify which key was used. The portion after the second underscore is the secret and is never logged.

API root

All v1 endpoints are served under:

https://api.journalify.app/api/v1/

Send the key

Pass the full key in the Authorization header as a Bearer token. The /whoami endpoint is the cheapest way to verify a key is wired up correctly:

curl -sS https://api.journalify.app/api/v1/whoami \
  -H "Authorization: Bearer jnf_abc12345_yourSecretHere"

A successful response looks like this:

{
  "api_key_id": "jnf_abc12345",
  "tenant_id": "ten_5f3a9c",
  "scopes": ["stories:read", "stories:write", "media:read"],
  "rate_limit": {
    "burst_per_second": 60,
    "daily": 100000
  },
  "expires_at": null
}

Scopes

Each key is granted explicit scopes. Calls to endpoints outside the granted scopes return HTTP 403 with a JSON body explaining which scope is missing.

  • stories:read — list, read, and search stories
  • stories:write — create, update, publish, and unpublish stories
  • media:read — list and read media library items
  • media:write — upload, update, and delete media
  • assignments:read — list and read assignments
  • assignments:write — create and update assignments
  • webhooks:manage — create, update, and delete webhook subscriptions

Grant the narrowest set of scopes your integration needs. If your service only reads published stories, do not include stories:write.

Rate limits

Limits are enforced per API key, not per tenant. Two windows are applied independently:

  • Burst: 60 requests per second
  • Daily: 100,000 requests per UTC calendar day

When either limit is exceeded the API returns HTTP 429 with a Retry-After header (seconds) and a JSON body containing window and remaining counters. Back off and retry — do not hammer the endpoint.

Expiry and revocation

Keys can be created with or without expires_at. Expired keys return HTTP 401 with code key_expired. Any key can be revoked instantly from the API Keys tab; revoked keys return HTTP 401 with code key_revoked from the next request onward.

Best practice: rotate production keys every 90 days. Create the new key, deploy your service with it, then revoke the old one once you have confirmed traffic on the new key in your logs.

Was this article helpful?

Was this helpful?

Can't find what you need, or spot something wrong? Let us know — every article is improved based on customer feedback.

Contact support