Inbound webhooks are the one place you call the Data API directly — no SDK is needed because the caller is an external service, not your app’s JavaScript.
Endpoint
{token} is the full plaintext token shown in the HASP dashboard when you create the webhook. No X-Hasp-AppId header or session cookie is needed — the token identifies both the app and the target entity. The token is an address, not a credential: every request must also carry a valid signature (see Signing).
Max body size: 256 KB.
Signing
Every request must be signed with the webhook’s signing secret, shown once in the dashboard when you create the webhook. Requests without a valid signature are rejected with401 UNAUTHORIZED and no record is created.
The scheme is HMAC-SHA256 over the timestamp and the raw request body:
- Take the current Unix time in seconds as
timestamp. - Build the signed string
"{timestamp}.{raw_body}"— the timestamp, a literal., then the exact bytes you send as the body. - Compute the HMAC-SHA256 of that string keyed by the signing secret, hex-encoded.
- Send two headers:
If you configured a custom signature header on the webhook, send the signature in that header instead of
X-Webhook-Signature. The timestamp header name does not change.
The timestamp must be within ±300 seconds of HASP’s clock; anything older or further in the future is rejected, so a captured request cannot be replayed later. Because the body is part of the signed string, changing either the body or the timestamp invalidates the signature — sign the bytes exactly as you send them.
Rotating the secret: after you rotate the signing secret, requests signed with the previous secret are still accepted for 7 days, so you can roll the new secret out to your sender without dropping requests.
If the webhook has an IP allowlist, requests from any other address are rejected with 403 IP_NOT_ALLOWED before the signature is checked.
Idempotency
Include anX-Idempotency-Key header (max 255 characters) to prevent duplicate records from replayed or retried requests. HASP caches the response for 24 hours — repeat requests with the same key return the original response without creating a second record.
Request
422 INVALID_PAYLOAD, and no record is created. A rejected body does not consume its X-Idempotency-Key, so a corrected retry with the same key is processed normally.
Keys are mapped to entity field keys according to the webhook’s field mapping (if configured). Unmapped keys are passed through directly. Keys that do not match any entity field are silently dropped.
Response
201 Created:Error Responses
Loop Prevention
If the request contains anX-Hasp-Webhook-Id header (set automatically on all outbound webhook deliveries), the record.created event is not re-dispatched. This prevents outbound → inbound → outbound infinite loops.