Guider · REST API
Motta og verifiser callbacken
En forespørsel med en callbackUrl avsluttes med en signert POST til den URL-en: svarene når mottakeren sender inn, eller beskjed om at den utløp eller ble kansellert. Denne guiden kjører en mottaker på maskinen din, sjekker signaturen, og skriver ut svarene.
Last checked
Du trenger et API-token og et publisert skjema, som beskrevet i Send en forespørsel med REST API-et tidligere, og Node eller Python på maskinen din. Hva en callback bærer, og hvordan nye forsøk fungerer, er i Callbacks og signering.
1. Kopier signeringshemmeligheten
formbase signerer hver callback med arbeidsområdets signeringshemmelighet for forespørsler. Åpne OAuth og API-nøkler i arbeidsområdets sidepanel og finn kortet Signeringshemmelighet for forespørsler:

Klikk kopiknappen og behold hemmeligheten i en miljøvariabel i terminalen der mottakeren din kommer til å kjøre:
export FORMBASE_SIGNING_SECRET='rqs_...'Ikke regenerer den
Den tredje knappen lager en ny hemmelighet, og den gamle slutter å virke med én gang, også for callbacker som allerede er underveis. Du trenger den ikke for å følge denne guiden.
2. Skriv mottakeren
Lagre verify-funksjonen fra Callbacks og signering ved siden av mottakeren din:
som verify.mjs for Node, siden den bruker import, eller som verify.py for Python. Mottakeren leser
den rå kroppen, sjekker signaturen, og først da tolker den JSON-en:
import http from 'node:http'
import { verifyFormbaseCallback } from './verify.mjs'
const secret = process.env.FORMBASE_SIGNING_SECRET
http
.createServer((req, res) => {
const chunks = []
req.on('data', (chunk) => chunks.push(chunk))
req.on('end', () => {
const rawBody = Buffer.concat(chunks).toString('utf8')
const signature = req.headers['x-formbase-signature'] ?? ''
if (!verifyFormbaseCallback(rawBody, signature, secret)) {
console.log('rejected: bad signature')
res.writeHead(401).end()
return
}
const event = JSON.parse(rawBody)
console.log(event.type, event.data.request.externalId, JSON.stringify(event.data.answers))
res.writeHead(200).end()
})
})
.listen(8787)import json, os
from http.server import BaseHTTPRequestHandler, HTTPServer
from verify import verify_formbase_callback
SECRET = os.environ['FORMBASE_SIGNING_SECRET']
class Handler(BaseHTTPRequestHandler):
def do_POST(self):
raw_body = self.rfile.read(int(self.headers['Content-Length']))
signature = self.headers.get('X-formbase-Signature', '')
if not verify_formbase_callback(raw_body, signature, SECRET):
print('rejected: bad signature', flush=True)
self.send_response(401)
self.end_headers()
return
event = json.loads(raw_body)
print(event['type'], event['data']['request'].get('externalId'), event['data'].get('answers'), flush=True)
self.send_response(200)
self.end_headers()
HTTPServer(('', 8787), Handler).serve_forever()Hash kroppen nøyaktig slik den ankom. Å tolke den og gjøre den tilbake til JSON endrer bytene, og signaturen stemmer ikke lenger.
3. Kjør den og gi den en offentlig URL
Start mottakeren:
node receiver.mjs # or: python3 receiver.pyformbase kaller bare offentlige HTTPS-adresser, så localhost duger ikke. Mens du tester, gir en tunnel maskinen din én.
Cloudflares hurtigtunnel
trenger ingen konto. Kjør den i en ny terminal:
cloudflared tunnel --url http://localhost:8787Den skriver ut en adresse som https://horn-cod-classics-arab.trycloudflare.com. ngrok og lignende verktøy fungerer på samme
måte. I produksjon, bruk serverens egen HTTPS-URL i stedet.
4. Send en forespørsel med en callback-URL
Opprett en testforespørsel som i forrige guide, og legg til
callbackUrl med tunnel-adressen. Bruk din egen skjema-ID:
curl -X POST https://api.formbase.so/api/v1 \
-H "Authorization: Bearer $FORMBASE_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"method": "requests.create",
"params": {
"formId": "jx75hdx8vb5hy1x85gm17nqgkn8f674g",
"recipient": { "email": "ada@acme.example", "name": "Ada Lovelace" },
"prefill": { "company_name": "Analytical Engines Ltd" },
"readonly": ["company_name"],
"externalId": "supplier-2044",
"idempotencyKey": "supplier-2044",
"callbackUrl": "https://horn-cod-classics-arab.trycloudflare.com/formbase",
"test": true
}
}'Bruk en ny idempotencyKey: samme nøkkel med en annen kropp blir avvist. Åpne url fra svaret, svar på skjemaet,
og send inn.
5. Se callbacken ankomme
Noen sekunder etter at du sender inn, skriver mottakeren ut hendelsestypen, din eksterne ID og svarene. Node-mottakeren skriver ut:
request.completed supplier-2044 {"certificate_of_incorporation":[{"name":"certificate-of-incorporation.pdf","size":635,"type":"application/pdf","url":"https://api.formbase.so/api/storage/...",...}],"company_name":"Analytical Engines Ltd","contact_email":"ada@acme.example","do_you_accept_our_30_day_payment_terms":"yes","vat_number":"GB123456789"}For å se en avvisning, send mottakeren en hvilken som helst POST selv, for eksempel
curl -X POST -d ‘’ http://localhost:8787. Den har ingen gyldig signatur, så mottakeren skriver ut
rejected: bad signature og svarer 401.
Før du går live
Svar 2xx innen 10 sekunder. formbase merker callbacken levert på enhver 2xx. En 5xx, en 408, en 429 eller en tidsavbrudd får nye forsøk i om lag fire timer; enhver annen 4xx, som 401-en over, stopper forsøkene. Se Nye forsøk.
Forgren på
type.Samme URL hører også
request.expiredogrequest.canceled, som ikke bærer noen svar.Håndter hver hendelse én gang. Et nytt forsøk bærer samme
id. Lagre IDene du har håndtert og hopp over en gjentakelse.Sjekk
test.En callback fra en testforespørsel har
“test”: true. Fjerntestfrarequests.createfor ekte mottakere.
Hvis mottakeren din var nede lenger enn forsøkene varer, er svarene ikke tapt. Les dem med requests.get, eller send
callbacken på nytt med requests.replayCallback eller fra
Forespørsler-siden.