5-minute quickstart with curl

Generate a key, verify it, subscribe a webhook, trigger an event, and verify the signature — end to end in five steps.

5 min read

What you will end up with

A working API key, a webhook subscription pointed at a test inbox, and a verified signature on the first delivery. Total time: under 5 minutes.

Step 1 — Create an API key and webhook secret

  1. Sign in to your Journalify newsroom.
  2. Open the Webhooks page and switch to the API Keys tab.
  3. Click "Create key", name it "quickstart", and grant scopes: stories:read, stories:write, webhooks:manage.
  4. Copy the key — it is shown once. Paste it into a terminal variable: export JNF_KEY=jnf_abc12345_yourSecretHere
  5. Switch to the Webhooks tab, click "Create endpoint" later — first capture a destination URL in step 3.

Step 2 — Verify the key with /whoami

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

Expected response:

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

If you see HTTP 401 with code key_invalid, double-check the full key (including the jnf_<prefix>_ portion) is on the Authorization header.

Step 3 — Get a test webhook destination

For local testing, the easiest destination is a free request-inspector service. Open https://webhook.site in a new tab — it gives you a unique URL like https://webhook.site/abc123-... that captures every request sent to it. Copy that URL.

For development on your own laptop you can also use a tunnel like cloudflared or ngrok to expose your local server publicly. Webhook.site is fine for the quickstart — swap it for your real endpoint when you are ready.

Step 4 — Subscribe a webhook

Replace YOUR_DESTINATION with the URL from step 3. The response includes the secret you will use to verify signatures — save it.

curl -sS -X POST https://api.journalify.app/api/v1/webhooks \
  -H "Authorization: Bearer $JNF_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "YOUR_DESTINATION",
    "events": ["story.published"]
  }'

Response (the secret is returned once — store it now):

{
  "id": "wh_2c8e1f",
  "url": "https://webhook.site/abc123-...",
  "events": ["story.published"],
  "secret": "whsec_yourWebhookSecretHere",
  "created_at": "2026-05-23T09:00:00Z"
}

Save the secret to your shell:

export JNF_WHSEC=whsec_yourWebhookSecretHere

Step 5 — Trigger a story.published event

The fastest path is to publish a story from the newsroom UI: open the newsroom, create a draft story called "Quickstart test", click Publish. Within a few seconds, webhook.site shows a new request — that is your story.published delivery.

Look at the request headers in webhook.site — you will see:

X-Journalify-Signature: t=1716470400,v1=4f1a...c92e
X-Journalify-Timestamp: 1716470400

Step 6 — Verify the signature

Copy the raw request body and the X-Journalify-Signature header value out of webhook.site, then run this Node.js one-liner to confirm the signature is valid:

// node verify.js
const crypto = require('node:crypto');

const secret = process.env.JNF_WHSEC;
const sigHeader = process.argv[2];   // pasted from webhook.site
const rawBody  = process.argv[3];    // pasted from webhook.site

const parts = Object.fromEntries(
  sigHeader.split(',').map((kv) => kv.split('=', 2)),
);
const signed = `${parts.t}.${rawBody}`;
const expected = crypto
  .createHmac('sha256', secret)
  .update(signed)
  .digest('hex');

const a = Buffer.from(expected, 'hex');
const b = Buffer.from(parts.v1, 'hex');
console.log(
  a.length === b.length && crypto.timingSafeEqual(a, b)
    ? 'signature OK'
    : 'signature MISMATCH',
);

Run it:

node verify.js \
  't=1716470400,v1=4f1a...c92e' \
  '{"id":"evt_01HXYZABC123","type":"story.published",...}'

If you see "signature OK", your end-to-end flow is wired correctly. From here, replace webhook.site with your own service and add the verification logic to your handler — see Verifying webhook signatures for production-grade snippets.

Next steps

  • Read Authenticating with API keys for the full scope model and rate-limit details.
  • Read Verifying webhook signatures for production Node.js and Python handlers.
  • Browse Webhook events you can subscribe to for the full event catalogue and payload shapes.
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