Webhookit
Bona Fide lähettää päätepisteeseesi HTTPS-POST-pyynnön jokaisesta kirjekuoritapahtumasta, jonka tilaat. Toimitukset
noudattavat Standard Webhooks -määritystä, joten mikä tahansa sen kirjastoista
voi tarkistaa ne.
Päätepisteen rekisteröinti
Osio nimeltä “Päätepisteen rekisteröinti”Kohdassa Asetukset › Webhookit tai API-avaimella, jolla on
käyttöoikeusalue org:manage:
curl https://api.bonafidesign.com/v1/webhook-endpoints \ -H "Authorization: Bearer $BONA_FIDE_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "https://app.example.com/hooks/bona-fide", "description": "Production", "events": ["envelope.completed", "envelope.sealed", "envelope.declined"] }'Vastauksessa on secret (whsec_…), vain tämän kerran. Tyhjä events-luettelo tilaa kaikki tapahtumat.
URL-osoitteen on oltava julkinen https://-osoite. Päätepiste kuuluu yhteen tilaan: testiavaimella luodut
päätepisteet vastaanottavat vain testitilan kirjekuorten tapahtumia ja tuotantotilan päätepisteet vain tuotannon
tapahtumia.
PATCH /v1/webhook-endpoints/{id} muuttaa URL-osoitetta, tapahtumia tai kuvausta ja keskeyttää tai jatkaa
päätepistettä (enabled). POST /v1/webhook-endpoints/{id}/test lähettää webhook.test-pingin.
Tapahtumat
Osio nimeltä “Tapahtumat”| Tyyppi | Milloin |
|---|---|
envelope.created |
Kirjekuori luotiin |
envelope.ready |
Asiakirja on renderöity, ja kirjekuori on valmis vastaanottajilleen |
recipient.sent |
Tuli vastaanottajan vuoro (ja sähköpostitoimituksessa hänen linkkinsä lähetettiin) |
recipient.viewed |
Vastaanottaja avasi allekirjoitussivun ensimmäisen kerran |
recipient.signed |
Vastaanottaja lähetti allekirjoituksen (tai hänen puolestaan allekirjoitettiin automaattisesti vastapuolena) |
recipient.declined |
Vastaanottaja kieltäytyi |
envelope.completed |
Kaikki vastaanottajat ovat valmiita. data.values sisältää muuttujat ja kaikki syötetyt arvot |
envelope.sealed |
Sinetöity PDF on valmis ladattavaksi |
envelope.declined |
Kirjekuori päättyi, koska vastaanottaja kieltäytyi |
envelope.voided |
Mitätöit kirjekuoren |
envelope.expired |
expiresAt umpeutui ennen valmistumista |
signing_link.used |
Vierailija aloitti kirjekuoren pysyvästä allekirjoituslinkistä |
acceptance.created on varattu skeemassa, eikä sitä vielä lähetetä.
Hyötykuorma
Osio nimeltä “Hyötykuorma”{ "id": "evt_9sKq2Lm4Tz", "type": "envelope.completed", "createdAt": "2026-10-13T14:09:52.004Z", "testMode": false, "data": { "envelope": { "id": "env_8Gm2kQ4rT1", "status": "completed", "seal": "pending", "recipients": [{ "id": "rcp_5Jw0pLs9Xe", "role": "client", "status": "completed", "…": "…" }], "externalId": "user_8841", "metadata": {}, "…": "…" }, "values": { "variables": { "client": { "name": "Acme Robotics, Inc." }, "effective_date": "2026-10-13" }, "recipients": { "client": { "client_title": "CEO", "start_date": "2026-11-01" } } } }}data.envelope on koko kirjekuori tapahtumahetkellä. data.values on vain tapahtumassa
envelope.completed: lähettämäsi muuttujat ja kunkin roolin kenttäarvot kentän tunnuksen mukaan.
Otsakkeet ja allekirjoitus
Osio nimeltä “Otsakkeet ja allekirjoitus”Jokaisessa toimituksessa on:
| Otsake | Arvo |
|---|---|
webhook-id |
Tapahtuman tunnus (evt_…); sama jokaisella uudelleenyrityksellä. Käytä sitä kaksoiskappaleiden poistoon |
webhook-timestamp |
Unix-sekunnit, jolloin tämä yritys allekirjoitettiin |
webhook-signature |
v1,<base64 HMAC-SHA256>, välilyönnein erotettuina, kun useampi kuin yksi salaisuus allekirjoittaa |
user-agent |
BonaFide-Webhooks/1 |
Allekirjoitus on HMAC-SHA256 merkkijonosta {webhook-id}.{webhook-timestamp}.{raw body}, ja avaimena on salaisuuden
whsec_-etuliitteen jälkeinen osa base64-dekoodattuna. Tarkista raaka runko (ennen JSON-jäsennystä), vertaa
vakioajassa ja hylkää aikaleimat, jotka poikkeavat kellostasi yli viisi minuuttia.
import express from 'express';import { Webhook } from 'standardwebhooks'; // npm i standardwebhooks
const wh = new Webhook(process.env.BONA_FIDE_WEBHOOK_SECRET!); // whsec_…const app = express();
app.post('/hooks/bona-fide', express.raw({ type: 'application/json' }), (req, res) => { let event; try { event = wh.verify(req.body, req.headers as Record<string, string>); // throws if forged or too old } catch { return res.sendStatus(400); } queue.add(event); // do the work asynchronously and answer quickly res.sendStatus(204);});# pip install standardwebhooks flaskimport osfrom flask import Flask, requestfrom standardwebhooks.webhooks import Webhook
wh = Webhook(os.environ["BONA_FIDE_WEBHOOK_SECRET"]) # whsec_…app = Flask(__name__)
@app.post("/hooks/bona-fide")def bona_fide(): try: event = wh.verify(request.get_data(), dict(request.headers)) except Exception: return "", 400 enqueue(event) return "", 204import { createHmac, timingSafeEqual } from 'node:crypto';
export function verify(secret: string, headers: Record<string, string>, rawBody: string) { const id = headers['webhook-id']; const ts = Number(headers['webhook-timestamp']); if (!id || !ts || Math.abs(Date.now() / 1000 - ts) > 300) throw new Error('stale or missing headers'); const key = Buffer.from(secret.replace(/^whsec_/, ''), 'base64'); const expected = createHmac('sha256', key).update(`${id}.${ts}.${rawBody}`).digest(); const ok = (headers['webhook-signature'] ?? '').split(' ').some((part) => { const [version, sig] = part.split(','); const given = Buffer.from(sig ?? '', 'base64'); return version === 'v1' && given.length === expected.length && timingSafeEqual(given, expected); }); if (!ok) throw new Error('bad signature'); return JSON.parse(rawBody);}Uudelleenyritykset
Osio nimeltä “Uudelleenyritykset”Toimitus onnistuu millä tahansa 2xx-vastauksella 10 sekunnin kuluessa. Uudelleenohjauksia ei seurata. Kaikkea muuta
yritetään uudelleen kasvavin viivein: 5 sekunnin, 5 minuutin, 30 minuutin, 2 tunnin, 5 tunnin, 10 tunnin, 14 tunnin,
20 tunnin ja 24 tunnin kuluttua, enintään kolmen päivän ajan tapahtumasta. Sen jälkeen toimitus merkitään
epäonnistuneeksi.
- Vastaa nopeasti ja käsittele asynkronisesti; poista kaksoiskappaleet
webhook-id-arvon perusteella. - Toimitukset voivat saapua väärässä järjestyksessä: tarkista
data.envelope.statussen sijaan, että olettaisit tietyn järjestyksen. GET /v1/webhook-endpoints/{id}/deliveriesluettelee viimeaikaiset yritykset tilakoodeineen, virheineen ja ajoituksineen, ja jokainen päätepiste näyttää 24 tunnin onnistumisprosenttinsa (health).POST /v1/events/{id}/redeliverlähettää tapahtuman päätepisteeseen uudelleen, esimerkiksi käyttökatkon jälkeen.
Salaisuuden kierto
Osio nimeltä “Salaisuuden kierto”POST /v1/webhook-endpoints/{id}/secret/rotate palauttaa uuden salaisuuden välittömästi. Seuraavien 24 tunnin ajan
jokainen toimitus allekirjoitetaan sekä uudella että vanhalla salaisuudella (kaksi merkintää otsakkeessa
webhook-signature), joten voit ottaa uuden salaisuuden käyttöön menettämättä tapahtumia.