Skip to content

Reservations Webhook ​

Record an external receipt update against an existing reservation cheque. This endpoint changes wallet/receipt data and requires an API key. Use sample records in an approved sandbox when testing it.

Current contract

The request uses reservationId, chequeId, receiptId, receiptAmount, and receiptStatus. Earlier examples using installmentId, chequeStatus, or reservationStatus do not match the current API. Existing heading links are retained below so bookmarks remain usable.

Overview ​

The API resolves the reservation and its wallet in the organization identified by your key, locates the cheque, maps your external receipt status, and records the external collection in a transaction. Obtain the assigned HTTPS host, sandbox key, existing reservation/cheque IDs, and supported receipt status mappings from Sakneen support.

Endpoint ​

POST /external/apis/v1.0/reservations/webhook

Try the interactive API reference, or download the Postman collection. Every playground write requires review and confirmation before it is sent.

Authentication ​

Supply the key in the api-key header. The key identifies the organization; a reservation outside that organization is not visible to it. Never place credentials in query strings.

Required Headers ​

HeaderValue
api-keyYour environment’s key; examples use YOUR_API_KEY_HERE
Content-Typeapplication/json

Request Body Schema ​

Required Fields ​

FieldTypeValidation
reservationIdstringExisting reservation MongoDB ObjectId, 24 hexadecimal characters
chequeIdstringExisting cheque MongoDB ObjectId, 24 hexadecimal characters
receiptIdstringNonempty external receipt identifier, at most 120 characters
receiptAmountnumberFinite, strictly positive amount
receiptStatusstringNonempty external receipt status, at most 120 characters; must have an organization mapping

Optional Fields ​

There are no documented optional fields for this callback. installmentId, chequeNumber, chequeAmount, chequeStatus, and reservationStatus are not substitutes for the required receipt fields.

Receipt status mappings ​

The callback uses receiptStatus instead of a fixed chequeStatus enum. Your organization maps external strings to wallet collection states such as confirmed, remitted, cleared, reversed, or unapplied. Ask support for the external values configured for your organization; do not assume the sample status is configured.

Reservation status ​

This callback does not accept a reservationStatus update. To create or update a reservation’s external status, use Reservations Management and POST /external/apis/v1.0/reservations with its required identifiers and status.

Behavior ​

Reservation status updates ​

A receipt mapped to confirmed, remitted, or cleared can mark the reservation’s down payment as collected and publish a reservation lifecycle event. It does not directly approve or cancel the reservation.

Cheque receipt updates ​

The callback resolves the reservation wallet and the cheque identified by chequeId, then records the amount, external receipt reference, and mapped collection status. Missing reservation, wallet, or cheque records return 404. An unmapped receipt status returns 422.

Request Examples ​

Replace both synthetic IDs with existing sandbox records and CONFIRMED with an external value mapped for your organization before sending.

bash
curl -X POST "https://your-assigned-domain/external/apis/v1.0/reservations/webhook" \
  -H "api-key: YOUR_API_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{
    "reservationId": "000000000000000000000001",
    "chequeId": "000000000000000000000002",
    "receiptId": "sample-receipt-001",
    "receiptAmount": 100,
    "receiptStatus": "CONFIRMED"
  }'

Approve a reservation ​

Sending reservationStatus: "approved" to this callback is not supported. Use the reservation upsert endpoint when you intend to change reservation status. Review that endpoint’s request body and asynchronous acceptance response.

Cancel a reservation ​

Sending reservationStatus: "canceled" to this callback is not supported. Use the reservation upsert endpoint with the external status configured for your organization.

Report a reversed receipt ​

Use the receipt request above with the organization’s configured external reversal status. Supply the appropriate receiptId and existing chequeId; chequeStatus: "bounced" is not the current callback contract.

Report a collected receipt ​

Use the receipt request above with a configured external value mapped to confirmed, remitted, or cleared. chequeStatus: "collected" is not the current callback contract.

Code Examples ​

Keep host and key in environment variables. The examples intentionally omit redirect following and automatic retries. Supply existing sandbox identifiers and a configured external receipt status.

JavaScript/Node.js ​

javascript
const response = await fetch(
  `https://${process.env.SAKNEEN_DOMAIN}/external/apis/v1.0/reservations/webhook`,
  {
    method: 'POST',
    redirect: 'error',
    headers: {
      'api-key': process.env.SAKNEEN_API_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      reservationId: '000000000000000000000001',
      chequeId: '000000000000000000000002',
      receiptId: 'sample-receipt-001',
      receiptAmount: 100,
      receiptStatus: 'CONFIRMED',
    }),
  },
);
if (!response.ok) throw new Error(`Receipt update failed: HTTP ${response.status}`);
// Success has an empty response body; do not call response.json().

Python ​

python
import os
import requests

response = requests.post(
    f"https://{os.environ['SAKNEEN_DOMAIN']}/external/apis/v1.0/reservations/webhook",
    headers={'api-key': os.environ['SAKNEEN_API_KEY']},
    json={
        'reservationId': '000000000000000000000001',
        'chequeId': '000000000000000000000002',
        'receiptId': 'sample-receipt-001',
        'receiptAmount': 100,
        'receiptStatus': 'CONFIRMED',
    },
    allow_redirects=False,
    timeout=30,
)
response.raise_for_status()
# A successful response is empty; do not parse it as JSON.

Python — Odoo Integration ​

Keep the assigned host, key, and external status mapping in server-side configuration. Reuse the Python request above with values from the actual receipt event.

Wiring it into an Odoo cheque model ​

Store the corresponding Sakneen reservation and cheque IDs on the integration record. Map the external receipt’s stable identifier to receiptId, its positive amount to receiptAmount, and its configured external status to receiptStatus. Do not use the old installmentId or chequeStatus fields.

PHP ​

php
$curl = curl_init('https://' . getenv('SAKNEEN_DOMAIN') . '/external/apis/v1.0/reservations/webhook');
curl_setopt_array($curl, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_FOLLOWLOCATION => false,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTPHEADER => [
        'api-key: ' . getenv('SAKNEEN_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'reservationId' => '000000000000000000000001',
        'chequeId' => '000000000000000000000002',
        'receiptId' => 'sample-receipt-001',
        'receiptAmount' => 100,
        'receiptStatus' => 'CONFIRMED',
    ]),
]);
curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
// Inspect $status. The success body is empty.

Response Format ​

A successful request returns 201 with an empty body. The transaction records the collection before the controller returns. Do not expect the older plain-text success message.

Error Handling ​

Common Error Responses ​

Missing API Key ​

401 — Access Denied, API key not provided.

Invalid API Key ​

401 — Access Denied, API key not valid. Confirm that your key is enabled for external access and belongs to the selected environment.

Validation Error ​

400 — missing or invalid required fields, invalid ObjectIds, nonpositive receipt amount, or invalid strings. Inspect the JSON validation error returned by the API.

Reservation / Wallet / Cheque Not Found ​

404 — the reservation, its wallet, or the matching installment is unavailable to the organization identified by your key.

Unsupported Receipt Status ​

422 — the supplied external receipt status is not mapped for your organization. Ask support for the supported mapping; this is not the older reservation-state-transition flow.

Best Practices ​

Idempotency ​

Use a stable receiptId for the same external receipt and an existing cheque ID. After an ambiguous network failure, inspect the affected record before deciding to repeat the callback. The playground does not automatically retry writes.

Error Handling ​

Handle validation, authentication, missing-resource, and unsupported-status errors separately. Browser network failures may also arise from CORS, CSP, TLS, or a blocked redirect; no proxy fallback is used.

Security ​

Use HTTPS, keep credentials out of URLs and logs, and test with an approved sandbox key. Never use customer records or production writes for playground verification.

Performance ​

Submit one receipt update per request. The operation changes wallet data in a transaction; wait for its response before repeating a request against the same receipt.

Integration Tips ​

Confirm the assigned host/key, external receipt status mappings, reservation/cheque linkage, and a cleanup plan with Sakneen support before running a controlled sandbox write. Use the public health check and a protected GET first.