Webhook API
A webhook belongs to one form. Another system posts a JSON body to it with a bearer secret; Pyn accepts the payload, then separately turns it into a submission on the form for the employee it names, logging the outcome on the webhook. Create a webhook covers the setup in the app.
Request
Section titled “Request”POST https://<your Pyn host>/api/webhook/<webhookId>Authorization: Bearer <secret>Content-Type: application/jsonIdempotency-Key: <any string> (optional)
{ "subject_id": "E1234", "fields": { "jobTitle": "Account Executive", "startedOnboarding": true, "firstWeekRating": 4 }}webhookIdand the secret come from the form’s Settings drawer. The secret is shown once when minted.subject_idis the employee’s id in the source system chosen under Subject on the form (for example a BambooHR Employee ID). Pyn finds the employee holding that id from that system; the same id from another system does not match.fieldsholds one entry per form field, named by the field’s alias (its label in camel case) or its key. Every key must name a field on the form, and every value must be one the field can hold: a string for Text,trueorfalsefor Checkbox, an integer 1 to 5 for Likert Scale, an employee id for Buddy and Mentor. Content fields take no value.- The body must be a JSON object. Nesting values under
fieldskeeps field names from colliding withsubject_id.
Responses
Section titled “Responses”| Status | Meaning |
|---|---|
202 |
Accepted. The payload was taken and will be processed; this does not mean the submission succeeded. Read the log. |
404 |
Rejected: the id is malformed or unknown, the webhook is archived, or the bearer secret does not match. The cases are not distinguished, so the endpoint cannot be probed. |
A request that reaches the endpoint with a body that is not JSON, or during a fault on Pyn’s side, is answered with the usual 4xx or 5xx; a 5xx can be retried.
Idempotency
Section titled “Idempotency”Send an Idempotency-Key header and a repeat of the same key to the same webhook is acknowledged with 202 and processed no further. The key is hashed with the webhook’s id, so the same key sent to a different webhook is a separate delivery. Without the header every post is processed. The key itself is not stored; the log’s eventId is the handle for tracing a delivery.
Processing rules
Section titled “Processing rules”- A webhook submits for an employee at most once. Once a subject’s submission is complete, later payloads for the same
subject_idare dropped withalready-submitted. A form that needs repeat answers from one person cannot use a webhook for them. - A payload is taken whole or not at all: a missing required field or a value of the wrong type drops the whole payload rather than recording a partial submission.
- A form with no Subject set accepts nothing (
no-subject). - An accepted submission behaves like any other: it appears in the form’s Activity drawer and export, writes Buddy or Mentor values to the employee, and starts any automation with a Form Submission trigger on the form.
Log codes
Section titled “Log codes”Every payload leaves one entry in the webhook’s log (the form’s Settings drawer, with a CSV export of the whole log).
| Code | Outcome | Meaning |
|---|---|---|
submitted |
Processed | Recorded a submission for the identifier. |
no-subject |
Dropped | The form has no webhook subject configured. |
invalid-payload |
Dropped | The body did not parse as { subject_id, fields }; the message names the field and reason. |
unknown-subject |
Dropped | No employee holds that identifier in the chosen source system. |
already-submitted |
Dropped | This webhook has already submitted for that identifier. |
ambiguous-fields |
Dropped | A name matched more than one field, or a field was named twice (by key and alias). |
missing-fields |
Dropped | A required field was not supplied. |
invalid-fields |
Dropped | A key names no field on the form, or a value is the wrong type for its field. |
Each dropped payload also raises a notice in Notices, keyed by its code, so a caller repeating one mistake updates a single notice.
Secrets
Section titled “Secrets”| Action | Effect |
|---|---|
| Create Secret | Mints the secret for a webhook that has none. A webhook without a secret accepts nothing. |
| Replace Secret | Mints a new secret; the old one stops working immediately. |
Secrets are shown once and cannot be read back. Both actions need an Admin.
Related
Section titled “Related”- Create a webhook for the steps in the app.
- Form field types for the values each field accepts.
- Notices for where dropped payloads surface.