Canonical
Webhooks
Generic HTTPS webhook destination for pushing Orakel records to any custom system.
Overview
The webhook destination type POSTs Orakel records to a user-supplied URL. Use it when there is no dedicated adapter for your target system, or when you want the raw record shape.
Each push is one HTTPS request. The body contains every company fetched for the request, with financials, roles, sub-units, and licenses attached.
Setup
- Create a destination of type
webhook:curl -X POST https://orakel.cloud/api/destinations \ -H "Authorization: Bearer $ORAKEL_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "my-webhook", "type": "webhook", "config": { "url": "https://ingest.example.com/orakel", "method": "POST", "headers": { "X-Tenant": "acme" } } }' - Trigger a push:
curl -X POST https://orakel.cloud/api/push/my-webhook \ -H "Authorization: Bearer $ORAKEL_KEY" \ -H "Content-Type: application/json" \ -d '{"orgNumbers": ["923609016","912345678"]}'
Payload shape
One POST per push call. The body wraps every company for the request in a single companies array:
{
"companies": [
{
"id": "...",
"orgNumber": "923609016",
"country": "NO",
"name": "Equinor ASA",
"orgFormCode": "ASA",
"naceCode1": "06.100",
"naceDescription1": "Utvinning av raolje",
"employeeCount": 21000,
"businessAddressStreet": "...",
"primaryDomain": "equinor.com",
"enrichedDomains": ["equinor.com"],
"technologies": [{ "name": "...", "category": "...", "confidence": 0.9 }],
"financials": [{ "periodTo": "2024-12-31", "revenue": 1000000000, "netResult": 100000000 }],
"roles": [{ "roleTypeCode": "DAGL", "personFirstName": "...", "personLastName": "..." }],
"subUnits": [{ "orgNumber": "...", "name": "..." }],
"licenses": [{ "licenseTypeCode": "01SKJE", "venueName": "..." }]
}
]
}The shape matches the Prisma Company model with financials, roles, subUnits, licenses included. See the CompanyWithRelations type in lib/push/adapters/types.ts for the authoritative structure.
Configuration
| Field | Type | Required | Description |
|---|---|---|---|
url |
string | yes | HTTPS endpoint. |
method |
string | no | Defaults to POST. |
headers |
object | no | Extra headers merged with Content-Type: application/json. |
{
"url": "https://ingest.example.com/orakel",
"method": "POST",
"headers": {
"X-Tenant": "acme",
"Authorization": "Bearer ..."
}
}Encrypted at rest (AES-256-GCM).
Security
- Always use HTTPS. Orakel does not emit secrets in the body, but API tokens you set in
headerstravel with every request. - Shared-secret auth: put your auth token in a custom header via
config.headers. The receiver verifies it. - Signature verification: the current webhook adapter does not sign the body. If you need HMAC signing, route through a custom adapter or add a signing proxy in front of your receiver.
- IP allowlisting: Orakel calls come from the Hetzner Helsinki egress. Contact
hello@orakel.cloudfor the current outbound IP range.
Push behavior
- One POST per
POST /api/push/:destinationNamecall, regardless oforgNumberslength. - Non-2xx response: the entire batch is marked failed and returned in the push result
errors[]. - Network error or timeout: same — whole batch fails.
- No retry. No exponential backoff. The caller retries by re-invoking
/api/push/:destinationName. - Receiver-side rate limiting is the receiver's problem. Batch sizes are bounded by the push endpoint's 100-org limit.
Gotchas
- All-or-nothing batch: one non-2xx fails the whole push. Split large batches into smaller pushes if your receiver is flaky.
- No built-in dedupe: the same org number pushed twice produces two requests. Key on
orgNumberreceiver-side. X-Forwarded-*handling: if your receiver sits behind a proxy and you verify any signature yourself, reconstruct the public URL before hashing. Orakel pushes straight, but internal receivers often don't.- TLS required: plain HTTP URLs are accepted at config time but should not be used. No guarantees about what intermediaries will do.
- Body size: companies carry nested financials, roles, sub-units, and licenses. A 100-org push can exceed several hundred KB.
Related
- Destinations endpoint — CRUD for destinations and push trigger
- Attio — dedicated adapter with upsert semantics
- HubSpot — dedicated adapter with OAuth and webhook-driven enrichment