Help centerDevelopers & automation

Webhooks

Get a signed JSON event at your URL whenever tasks change.

Webhooks settings
Settings → Developers: API & webhooks.

Add a webhook

  1. 1Open Settings → Developers: API & webhooks → Webhooks.
  2. 2Enter your https URL, for example a Zapier catch hook or your own server.
  3. 3Choose the events (all are on by default) and All projects or one project.
  4. 4Click Add webhook and copy the signing secret. You won't see it again.

Each webhook shows its status (Active, Recent deliveries failed or Paused), with buttons to send a test event, pause or resume, and delete.

Events

EventWhen
task.createdA task is created.
task.updatedRenamed, description, due date, priority, owner or stage changed; subtask or attachment added or removed; linked PR events.
task.completed / task.reopenedA task is completed or reopened.
task.deletedA task is deleted (the payload has the task as it was).
comment.createdA comment is added.
pingSent by the test button.

Custom field changes don't trigger task.updated.

Payload

POST https://your-server.com/jinkoup
X-JinkoUp-Event: task.completed
X-JinkoUp-Delivery: evt_…
X-JinkoUp-Signature: t=1791000000,v1=5f2c…

{
  "id": "evt_…",
  "type": "task.completed",
  "created_at": "2026-10-04T15:00:00Z",
  "workspace_id": "…",
  "actor": { "id": "…", "name": "Sara Kim", "email": "sara@acme.com" },
  "data": {
    "task": {
      "id": "…", "title": "Homepage hero concepts", "completed": true,
      "project": { "id": "…", "name": "Website relaunch" },
      "stage": "Review", "assignee": "Sara Kim <sara@acme.com>",
      "due_date": "2026-10-05", "priority": "high",
      "url": "https://jinkoup.com/projects/…?task=…"
    },
    "change": { "type": "completed", "message": "…" }
  }
}

Verify the signature

Compute HMAC-SHA256 with your signing secret over <t>.<raw body> (the t value from the header, a dot, then the exact request body) and compare it, hex-encoded, with v1. Reject events older than 5 minutes, and use X-JinkoUp-Delivery to ignore duplicates.

import crypto from "node:crypto";

function verify(rawBody, header, secret) {
  const { t, v1 } = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
  const expected = crypto.createHmac("sha256", secret).update(t + "." + rawBody).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1));
}

Delivery rules

  • Reply with a 2xx status within 8 seconds.
  • Server errors, 429s, timeouts and network errors are retried once.
  • After 20 failures in a row the webhook pauses itself. Fix your endpoint, then click Resume.
  • URLs must be public https addresses.
  • A webhook acts as the person who created it and only sends tasks they can see. Admins can see and manage every webhook in the workspace.

Still stuck? Tell us what you were trying to do and we'll help.

Contact support