Webhooks
A webhook is an https address you control. Ploti sends it a signed POST for each event, the moment it happens.webhooks createtakes the address and an optional description. It returns a signing secret once. Keep it with your receiver.- Over the REST API or the CLI, it also takes an optional header your receiver requires, such as a bearer key. Ploti sends it with every POST and never shows it again. An assistant cannot set one.
webhooks list,webhooks test(sends a signedping) andwebhooks deletemanage them.
{id, type, timestamp, data}, the same shape for every event. Answer 2xx quickly and do the work afterwards. A failed delivery is retried six times, at growing intervals, over about a day and a half.
A webhook made for a Data Feeds subscription receives only that subscription’s feed events. Every other webhook receives these three kinds of event:
Watch a dataset
datasets watch takes a dataset id. From then on, each new version sends a dataset.changed event to all your webhooks. datasets unwatch stops it, and datasets watches lists what you watch. Watching a dataset twice changes nothing.
A member may watch 100 datasets. Any kind of dataset can be watched, documents included, as long as your workspace’s coverage and plan open it.
data.versionis the new version: Ploti’s own number for the dataset’s published data, separate from Data Feeds version numbers.data.promotedAtis when it went live.data.countsis what it added, changed and removed.data.provenanceUrlsays where its values come from.
Read what changed
datasets changes with the event’s version lists exactly the rows it added, changed, removed or renamed (a record that now carries a new id). The added and changed rows of the latest version come with the row itself.
changeLog says what was recorded for the version:
recorded: every changed row is listed.counts_only: only the totals were kept. Read the dataset with your own conditions instead.ids_changed,full_refreshorfirst: the dataset’s ids were replaced, it was reloaded whole, or this is its first version, so there is no row-by-row list. Read it again withdatasets_rows.
Verify each delivery
Check the signature before acting on a POST. Ploti signs with Standard Webhooks, whose libraries do this for most languages:webhook-id: the delivery’s id, the same on each retry. To skip an event you’ve already handled, check theidin the body.webhook-timestamp: Unix seconds when it was signed. Reject one more than 5 minutes old.webhook-signature:v1,<base64>, an HMAC-SHA256 of<webhook-id>.<webhook-timestamp>.<raw body>keyed with the base64 bytes afterwhsec_in the secret. Compare in constant time. While a secret rotates, several signatures are sent, separated by spaces, and any one matching is enough.
Request events
data_request.sourcing,.matched,.checkpoint_released(the first results arrived),.ready,.failed,.cancelled,.paid_source,.cycle_refused,.question(Ploti needs the member’s answer, given in Ploti) and.question_reminder.research_request.report_ready(Ploti’s check reported what data exists and what is missing),.question(the check needs the member’s answer;data.questionshas the questions, andrequests questions answersends the answers),.answered(data.answer) and.needs_attention(the research can’t finish on its own).
data.url on a request event opens the request in Ploti.