Skip to content
Hub Nexus
Updated

AuthorCanonset

See something to improve? Propose a change.

Support

This page is public.

First published at canonset.com.

Your company can register one HTTPS endpoint, and Canonset POSTs a small signed JSON event when something you picked happens: an answer is approved, or a project is completed. Events carry IDs, never answers; pull those through the API. Each delivery is signed with a secret shown to you once.

Setting it up

On API in your client account, enter an https:// address on your side that accepts POST requests, and tick the events you want:

  • answer.approved: an answer is approved and ready to export.
  • project.completed: a project is completed.

Saving a new endpoint shows its signing secret once; copy it then. You can roll the secret, send a test event, and remove the webhook (its delivery log goes with it). The URL must point to a public server over https, with no credentials in it: verify our signature instead.

What an event looks like

Each event is JSON: {"id", "type", "created", "data"}.

  • answer.approved data: project_id, task_id, approved_at.
  • project.completed data: project_id, completed_at.
  • A test event has the type ping and a short message.

Three headers come with it: Canonset-Signature (below), Canonset-Event (the event's type) and Canonset-Delivery (the event's ID). Use Canonset-Delivery to ignore repeats. Events can arrive out of order.

Verifying the signature

Canonset-Signature is t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<raw body>" with your secret>, the same scheme as Stripe's. Compute the HMAC over the timestamp, a dot and the raw request body exactly as received, compare it with v1 in constant time, and reject timestamps more than 5 minutes from your clock. In Node.js:

const [t, v1] = req.headers["canonset-signature"].split(",").map((p) => p.split("=")[1]);
const expected = crypto.createHmac("sha256", process.env.CANONSET_WEBHOOK_SECRET)
  .update(`${t}.${rawBody}`).digest("hex");
const fresh = Math.abs(Date.now() / 1000 - Number(t)) < 300;
const valid = fresh && v1?.length === expected.length && crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(expected));

Deliveries are signed with the secret current when they are sent, so after you roll the secret, new deliveries and retries use the new one.

Answering

Answer with any 2xx status within 10 seconds. We don't follow redirects. A timeout or any other status counts as a failed delivery.

Retries and the delivery log

A failed delivery is retried after 1, 5, 30, 120 and 720 minutes. After the last retry it stays failed until you press Send again on the API page, which sends it now. When a delivery gives up after its last retry, everyone at your company is emailed that we couldn't reach your endpoint, with what it said, at most once a day (not for test events).

The API page lists your last 20 deliveries with the event, its status, the HTTP status your endpoint returned, the number of tries and the last error. The log keeps 30 days.

Deleting all of your company's data also removes the webhook. See The Canonset API for the endpoints the events point you to.

Questions: support@canonset.com.

In these publicationsCanonset help center

LanguagesEnglish

Licence: All rights reserved

Views

Comments

Spinner Logo
By Canonset
Welcome to Canonset
By Canonset
Canonset Walkthroughs
By Canonset
Canonset Founder's Intro Video
By Canonset

No description yet

By Canonset
What Canonset pays for, when the money goes out, how it reaches your bank, and what happens to pay when an answer is returned, not accepted or replaced after delivery.
By Canonset
What a return means and how to fix and resend, what not accepted means for your pay and score, how to ask for a second look, the pre-check before you send, and the warning that comes before any deactivation for quality.