Webhook Interface
| Available in API versions | v4 |
|---|
About the API
Why is it called the “webhook” interface?
The webhook interface relies on webhooks implemented by the POS or by the component integrating with Qerko. Webhooks deliver Qerko’s requests to your system.
Comparison with /v2 Websocket API
Compared to the WebSocket API, the POS does not need to manage a stateful connection. The webhook interface is stateless and therefore easier to host. If you cannot expose a publicly accessible HTTP endpoint, for example because of network limitations on the POS side, use the WebSocket interface instead.
Communication overview
- Communication is bidirectional: Qerko can request operations from the POS, and the POS can request information from Qerko.
- When the POS needs to call Qerko, use the REST API endpoints.
- When Qerko needs to call the POS, it invokes one of the webhooks implemented by the POS.
- Every request received by Qerko from the POS must include the assigned API key in the
Authorizationheader and the Pos-Id in thePos-Idheader. Authorization failures result in HTTP status401. - Requests with an invalid payload shape (for example a missing
paymentIdin/get-payment) receive HTTP status400. - All webhook communication is signed. Qerko provides two signature mechanisms for webhook validation: RFC 9421 and HMAC-SHA-256. Use your API key as the shared secret.
- For RFC 9421, Qerko sends the
SignatureandSignature-Inputheaders. - For HMAC-SHA-256, Qerko sends the
Signature-SHA256header. - If the POS detects a signature mismatch, respond with HTTP status
401. - The
createdandexpirestimestamps are part of the signature input. Any tampering invalidates the signature. Both timestamps are present in every webhook request to protect against replay attacks. Treat webhook calls with invalid timing as HTTP410. - Respond to webhooks either synchronously with HTTP
200or asynchronously with HTTP202. An asynchronous response tells Qerko to expect the final result via the/replyendpoint. - Both synchronous and asynchronous responses have a 15-second timeout. After 15 seconds without a response, the webhook is considered stale.
- Qerko validates the POS responses to every webhook. If validation fails, Qerko invokes the
errorevent and provides additional context. - Qerko automatically retries webhook calls that receive HTTP
500from the POS, up to three attempts.
Configuring endpoints per merchant
You can configure a webhook per merchant (restaurant). Call the one-time /configure endpoint to associate a webhook URL with the merchant’s API key. This approach lets you host generalized endpoints such as /webhook/:merchant-id.
Synchronous or asynchronous?
Use synchronous responses for short methods that the POS can process immediately. Use asynchronous responses for background tasks that exceed the 15-second timeout. In that case, return HTTP 202 and send the final result via /reply once processing is complete.
The API reference lists supported response types for every webhook:
202- asynchronous response allowed200- synchronous response allowed
Communication overview
Setting up your webhook
Synchronous flow
Asynchronous flow
Full integration steps
1. Set up your API key
Contact techsupport@qerko.com to access Qerko Administration, where you can create your sandbox environment and API keys.
Start implementing the API in the sandbox to make sure your webhooks work correctly before deploying to production.
If you run into issues from this step onward, continue coordinating with techsupport@qerko.com.
2. Prepare your authorization headers for sandbox
QERKO_API_KEY="<<YOUR_API_KEY_FROM_PREVIOUS_STEP>>"
# Alternatively use any uuid generator online tool to set up this variable
QERKO_POS_ID=$(which uuidgen >/dev/null && (uuidgen | tr '[:upper:]' '[:lower:]') || echo "59afcffa-6793-407b-9b31-d61652ec0209")| HTTP Header | Value |
|---|---|
Authorization | Bearer YOUR_API_KEY_FROM_PREVIOUS_STEP |
Pos-Id | uuidv4 (for production this value is assigned by Qerko) |
3. Test your authorization headers against the sandbox REST API
Send a request to /api/v4/who-am-i to verify your headers:
curl --request POST \
--url https://sandbox.qerko.com/api/v4/pos/who-am-i \
--header 'Accept: application/json' \
--header 'Authorization: Bearer '"$QERKO_API_KEY" \
--header 'Content-Type: application/json' \
--header 'Pos-Id: '"$QERKO_POS_ID"4. Configure your webhook endpoint for your API key
Call /api/v4/configure to associate your API key with your webhook endpoint:
QERKO_WEBHOOK_URL="https://your-unique-webhook-origin.com/merchant-specific-pathname"
curl --request POST \
--url https://sandbox.qerko.com/api/v4/pos/configure \
--header 'Accept: application/json' \
--header 'Authorization: Bearer '"$QERKO_API_KEY" \
--header 'Content-Type: application/json' \
--header 'Pos-Id: '"$QERKO_POS_ID" \
--data '{
"webhookUrl": "'"$QERKO_WEBHOOK_URL"'"
}'5. Implement your functionality
5.1. Accessing the debugger
Open the POS debugging tool in Qerko Administration (see the left-side menu below).

5.2. Implementing the middleware scenarios
On the Qerko Administration debugger page, use the scenario dropdown to test your implementation. Focus on scenarios prefixed with v4, which correspond to this API version.

Start with scenarios your middleware must always handle, such as request preprocessing:
- Verify the unauthorized response for an invalid API key.
- Verify the expired request response.
5.2.1. Verify the request timing
Treat every request-timing error with HTTP 410.
Validate that req.body.created and req.body.expires fall within an acceptable window. req.body.expires should always be a future timestamp (greater than Date.now()).
If req.body.created is in the future, it can indicate either:
- The HTTP request genuinely arrived outside the allowed window.
- The clocks between Qerko and the POS are out of sync.
We recommend enforcing a tolerance of about one minute for req.body.created. Larger windows increase the risk of accepting malicious requests, while smaller windows make the integration fragile.
5.3. Implementing the signature verification
5.3.1. Verify content digest
Start by verifying the Content-Digest HTTP header, which should contain sha256:
request.headers['Content-Digest'] = SHA256(request.body)Treat any Content-Digest mismatch as HTTP 401.
5.3.2. Implement the verification
Choose one of the following verification strategies:
- RFC 9421 - recommended if your stack has a suitable library, such as
http-message-signaturesfor Node.js. - HMAC-SHA-256.
5.3.2.1. RFC 9421
For RFC 9421, follow the library instructions and use your API key as the shared secret. Qerko includes all required data in the HTTP headers:
Signature-InputSignature
5.3.2.2. HMAC-SHA-256
The HMAC-SHA-256 signature is sent in the Signature-SHA256 header. Qerko includes this header in every webhook request as an alternative if RFC 9421 is difficult to implement in your stack.
Note: request.body includes the created and expires timestamps to prevent timing forgery.
5.4. Implementing basic methods
Implement the fundamental webhook methods:
- Verify that you accept the
pingevent. - Verify that you accept the
errorevent (used for asynchronous error reporting). - Verify your response to unsupported methods.
Note: The ping method is required. Qerko uses it for periodic health checks against the POS.
5.4.1. Futureproofing your implementation
The unsupported-method scenario keeps your integration future-proof. If Qerko releases functionality you have not implemented, it should fall back to a clear response. Because all webhook events are delivered to a single endpoint, think of the handler as a large switch / case statement where the default branch returns HTTP 404 to Qerko.
5.5. Test the basic methods
Before moving on, make sure each scenario works, especially ping and error reporting.
5.6. Full POS functionalities
Implement the functionalities you plan to support. You can test them directly in the debugger tool.
Note: Additional testing scenarios are being added over time.
6. Reconfigure for production
Complete these final steps before going live:
- Reach out to
techsupport@qerko.com. - Qerko will test your implementation to confirm production readiness.
- Update your configuration:
- Replace the
sandbox.qerko.comhostname withqerko.com. - Replace the temporary
Pos-Idwith the uuidv4 value assigned by Qerko.
- Replace the
7. All set
Your webhook integration is ready. Continue with end-to-end testing and monitoring in your environments.
Need help? Contact techsupport@qerko.com for assistance.