DocumentationWebhook interface

Webhook Interface

Available in API versionsv4

API Reference

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

  1. Communication is bidirectional: Qerko can request operations from the POS, and the POS can request information from Qerko.
  2. When the POS needs to call Qerko, use the REST API endpoints.
  3. When Qerko needs to call the POS, it invokes one of the webhooks implemented by the POS.
  4. Every request received by Qerko from the POS must include the assigned API key in the Authorization header and the Pos-Id in the Pos-Id header. Authorization failures result in HTTP status 401.
  5. Requests with an invalid payload shape (for example a missing paymentId in /get-payment) receive HTTP status 400.
  6. 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.
  7. For RFC 9421, Qerko sends the Signature and Signature-Input headers.
  8. For HMAC-SHA-256, Qerko sends the Signature-SHA256 header.
  9. If the POS detects a signature mismatch, respond with HTTP status 401.
  10. The created and expires timestamps 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 HTTP 410.
  11. Respond to webhooks either synchronously with HTTP 200 or asynchronously with HTTP 202. An asynchronous response tells Qerko to expect the final result via the /reply endpoint.
  12. Both synchronous and asynchronous responses have a 15-second timeout. After 15 seconds without a response, the webhook is considered stale.
  13. Qerko validates the POS responses to every webhook. If validation fails, Qerko invokes the error event and provides additional context.
  14. Qerko automatically retries webhook calls that receive HTTP 500 from 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 allowed
  • 200 - 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 HeaderValue
AuthorizationBearer YOUR_API_KEY_FROM_PREVIOUS_STEP
Pos-Iduuidv4 (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).

debugger in menu

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.

debugger scenarios

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:

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-Input
  • Signature
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 ping event.
  • Verify that you accept the error event (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:

  1. Reach out to techsupport@qerko.com.
  2. Qerko will test your implementation to confirm production readiness.
  3. Update your configuration:
    • Replace the sandbox.qerko.com hostname with qerko.com.
    • Replace the temporary Pos-Id with the uuidv4 value assigned by Qerko.

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.