Webhook Integration
SolaBill customer callbacks describe the exact Orchida-backed application evidence retained by SolaBill. They are not callbacks sent by Orchida and do not replace status reconciliation.
Current Events
| Event | Meaning |
|---|---|
einvoice.submission.updated | An Orchida submission or validation result was retained. |
einvoice.status.changed | At least one provider-validation, Orchida invoice, tax-authority, or receiver state changed. |
einvoice.terminal | All regulated outcome dimensions reached terminal states. |
einvoice.incoming.received | A new Orchida purchase document was retained. |
einvoice.incoming.revised | Orchida supplied a changed revision of a retained purchase document. |
Create subscriptions through POST /api/v1/webhooks/subscriptions. The destination must use HTTPS and cannot contain credentials, a query string, or a fragment. The signing secret is returned once. Deactivation retains the subscription and delivery evidence.
Headers
| Header | Description |
|---|---|
X-Webhook-Event | Exact event name. |
X-Webhook-Delivery | Stable event UUID; use it for idempotency. |
X-Webhook-Timestamp | UTC ISO-8601 event time used in the signature base string. |
X-Webhook-Signature | v1= followed by a lowercase HMAC SHA-256 digest. |
Envelope
{
"schema_version": "solabill-webhook-v2",
"id": "stable-event-uuid",
"event": "einvoice.status.changed",
"resource_type": "submission",
"resource_id": "123",
"occurred_at": "2026-08-18T10:00:00+00:00",
"payload": {
"submission_state": "accepted_by_provider",
"provider_invoice_state": "accepted",
"tax_authority_state": "accepted",
"receiver_state": "accepted"
}
}
The provider-validation, top-level Orchida invoice, authority and receiver dimensions remain separate. Never infer network exchange, authority reporting or receiver acceptance from another state or HTTP 2xx.
Signature Verification Example (PHP)
$payload = file_get_contents('php://input');
$timestamp = $_SERVER['HTTP_X_WEBHOOK_TIMESTAMP'] ?? '';
$provided = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$expected = 'v1='.hash_hmac('sha256', $timestamp.'.'.$payload, $secret);
if (! hash_equals($expected, $provided)) {
http_response_code(401);
exit('invalid signature');
}
Delivery Rules
- Respond with HTTP 2xx quickly after signature and timestamp validation.
- Process the event asynchronously in your application worker.
- Store event IDs to protect against duplicate callback retries.
- Retries occur only for transport errors, HTTP 408/409/425/429, and 5xx responses, with bounded exponential backoff.
- Redirects are not followed. A changed or unsafe destination is blocked and its subscription is deactivated.
- Continue periodic Orchida status reconciliation; a callback is notification, not the sole legal evidence source.