Skip to content

Developers

Developer guide

The Nabd REST API, signed webhooks, polling, incoming triggers and configuration guides per tool. Examples use placeholder values only.

Base URL

Requests and responses use JSON; BI feeds also support CSV. Request bodies are limited to 1 MB. JSON carries request_id in the body and X-Request-Id header; CSV carries it in the header.

https://nabdcx.com/api/public/v1

Authentication and scopes

Create a key in Settings › Integrations and send it in the Authorization header. The key is shown only once.

Authorization: Bearer nabd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  • read — read surveys, responses, summaries and feedback.
  • write — update feedback and manage contacts and invitations.
  • ingest — send new feedback.

The API is available on the Complete bundle and Enterprise. If an organisation loses access its keys stop working (403); nothing is deleted.

Rate limit

120 requests per minute per key. Above that you get 429 with a Retry-After header in seconds.

HTTP/1.1 429 Too Many Requests
Retry-After: 60

Pagination

Lists are cursor-based: limit defaults to 50, max 100. Pass next_cursor as cursor for the next page; it is null on the last page.

GET https://nabdcx.com/api/public/v1/feedback?limit=100&cursor=eyJ0Ijoi…

Errors

Every error has the same shape, with an English message and an Arabic message_ar.

{
  "error": {
    "code": "SCOPE_REQUIRED",
    "message": "This key does not have the required scope.",
    "message_ar": "لا يملك هذا المفتاح الصلاحية المطلوبة.",
    "details": { "required": "ingest", "granted": ["read"] }
  },
  "request_id": "req_…"
}
  • 400 BAD_REQUEST · INVALID_JSON
  • 401 UNAUTHORIZED · KEY_REVOKED · KEY_EXPIRED
  • 403 PLAN_REQUIRED · SCOPE_REQUIRED
  • 404 NOT_FOUND
  • 409 IDEMPOTENCY_CONFLICT · CONFLICT
  • 413 PAYLOAD_TOO_LARGE
  • 422 VALIDATION_FAILED
  • 429 RATE_LIMITED
  • 500 INTERNAL

Idempotency

Send an Idempotency-Key header (up to 100 characters) with POST requests. Same key + same body returns the same result; a different body returns 409 idempotency_conflict. Keys are kept for 24 hours.

Endpoints

GET /surveys · scope: read — List surveys with their real response count.

curl https://nabdcx.com/api/public/v1/surveys?limit=50 \
  -H "Authorization: Bearer nabd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
{
  "data": [
    {
      "id": "0b7c…",
      "title": { "ar": "رضا العملاء", "en": "Customer satisfaction" },
      "status": "active",
      "language": "ar",
      "workspace": { "id": "5d1e…", "name": "Main" },
      "created_at": "2026-10-01T09:00:00Z",
      "response_count": 412
    }
  ],
  "next_cursor": null,
  "request_id": "req_4f2a…"
}

GET /surveys/{id} · scope: read — Survey detail with its questions in order, options and scale ranges.

curl https://nabdcx.com/api/public/v1/surveys/0b7c… \
  -H "Authorization: Bearer nabd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
{
  "data": {
    "id": "0b7c…",
    "questions": [
      {
        "id": "q1", "type": "nps", "required": true,
        "text": { "ar": "ما مدى احتمال أن توصي بنا؟", "en": "How likely are you to recommend us?" },
        "scale": { "min": 0, "max": 10 }
      },
      {
        "id": "q2", "type": "single",
        "options": [{ "id": "opt_a", "label_ar": "الفرع", "label_en": "Branch" }]
      }
    ]
  },
  "request_id": "req_…"
}

GET /surveys/{id}/responses · scope: read — Completed real responses only (never test, synthetic or deleted). Anonymous surveys never include identity fields.

curl "https://nabdcx.com/api/public/v1/surveys/0b7c…/responses?since=2026-10-01T00:00:00Z&limit=100" \
  -H "Authorization: Bearer nabd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
{
  "data": [
    {
      "id": "r_91…",
      "submitted_at": "2026-10-12T14:03:11Z",
      "hidden_fields": { "branch": "riyadh" },
      "answers": [
        { "question_id": "q1", "type": "nps", "value": 9 },
        { "question_id": "q2", "type": "single_choice", "option_ids": ["opt_a"],
          "labels": [{ "ar": "الفرع", "en": "Branch" }] }
      ]
    }
  ],
  "next_cursor": "eyJ0Ijoi…",
  "request_id": "req_…"
}

GET /surveys/{id}/responses/{responseId} · scope: read — One response, same shape.

curl https://nabdcx.com/api/public/v1/surveys/0b7c…/responses/r_91… \
  -H "Authorization: Bearer nabd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
{ "data": { "id": "r_91…", "answers": [ … ] }, "request_id": "req_…" }

GET /surveys/{id}/summary · scope: read — Response count and, for each NPS/CSAT/CES question, the score computed with your organisation's own metric definitions.

curl "https://nabdcx.com/api/public/v1/surveys/0b7c…/summary?since=2026-10-01T00:00:00Z" \
  -H "Authorization: Bearer nabd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
{
  "data": {
    "survey_id": "0b7c…",
    "responses": { "total": 430, "completed": 412, "completion_rate": 0.958 },
    "questions": [
      { "question_id": "q1", "type": "nps", "answered": 398, "metric": "nps", "score": 42.5,
        "config": { "promoterMin": 9, "detractorMax": 6 } }
    ]
  },
  "request_id": "req_…"
}

GET /feedback · scope: read — Voice of the Customer items, filtered by date, source, status and case status.

curl "https://nabdcx.com/api/public/v1/feedback?since=2026-10-01T00:00:00Z&case_status=new" \
  -H "Authorization: Bearer nabd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
{
  "data": [
    { "id": "f_12…", "source": "email", "body": "…", "language": "ar", "sentiment": "negative", "case_status": "new" }
  ],
  "next_cursor": null,
  "request_id": "req_…"
}

GET /feedback/{id} · scope: read — One feedback item.

curl https://nabdcx.com/api/public/v1/feedback/f_12… \
  -H "Authorization: Bearer nabd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
{ "data": { "id": "f_12…", "case_status": "new", "themes": ["payment"] }, "request_id": "req_…" }

PATCH /feedback/{id} · scope: write — Update case status, resolution and due date (same validation and audit as the app).

curl -X PATCH https://nabdcx.com/api/public/v1/feedback/f_12… \
  -H "Authorization: Bearer nabd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{"case_status":"resolved","resolution_en":"Refund issued"}'
{ "data": { "id": "f_12…", "case_status": "resolved" }, "request_id": "req_…" }

POST /feedback · scope: ingest — Send one item. It goes through the same pipeline as a manual add (Nabd AI analysis, credits, plan limits, alerts). Repeating external_source + external_id returns the existing item with duplicate: true.

curl -X POST https://nabdcx.com/api/public/v1/feedback \
  -H "Authorization: Bearer nabd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 7f9d-2026-10-16-001" \
  -d '{
    "source": "email",
    "body": "تأخر الاسترداد أسبوعين",
    "language": "ar",
    "external_source": "zendesk",
    "external_id": "T-1042",
    "customer": { "email": "customer@example.com" },
    "metadata": { "channel": "support" }
  }'
{ "data": { "id": "f_88…", "duplicate": false }, "request_id": "req_…" }

POST /feedback/batch · scope: ingest — Up to 100 items per request, with one result per item.

curl -X POST https://nabdcx.com/api/public/v1/feedback/batch \
  -H "Authorization: Bearer nabd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{"items":[{"source":"email","body":"Great staff"},{"source":"email","body":"Late refund","external_source":"zendesk","external_id":"T-1042"}]}'
{
  "data": {
    "created": 1,
    "results": [
    { "index": 0, "status": 201, "id": "f_90…", "duplicate": false },
    { "index": 1, "status": 200, "id": "f_88…", "duplicate": true }
    ]
  },
  "request_id": "req_…"
}

Contacts and personal invitations

  • GET /contacts · read
  • GET /contacts/{id} · read
  • POST /contacts · write
  • POST /contacts/batch · write
  • PATCH /contacts/{id} · write
  • DELETE /contacts/{id} · write
  • POST /surveys/{id}/invitations · write
  • POST /surveys/{id}/invitations/batch · write
  • GET /surveys/{id}/invitations · read
  • GET /invitations/{id} · read
  • POST /invitations/{id}/cancel · write

POST /contacts upserts by external_source + external_id; an email or mobile collision under another identity returns CONFLICT. PATCH preserves omitted fields. DELETE erases identity and attributes, audits the operation and keeps answers. Batches accept items (up to 500) and return per-item results.

Contact filters: search, language, workspace_id, external_source, consent with channel (email or whatsapp), attribute_key with attribute_value, last_invited_before. Lists support limit and cursor; invitations also support status. Results never include secrets or token hashes.

Send exactly one of contact_id or contact, plus channel, with optional hidden_fields, send_at and expires_in_days. The link channel returns an /i/ URL for your system to send. Email and WhatsApp wait for the send window and daily cap; channel opt-out blocks sending. WhatsApp is Beta and disabled pending Unifonic confirmation. UI plan rules apply; Free does not include API access by default.

Linked GET responses and response.completed include contact {id, external_source, external_id} and invitation_id. Anonymous surveys retain invitation counts only: response identity links are not stored or exposed in results, API or webhooks. Erased contact identity is never returned.

{ "data": { "invitation_id": "550e8400-e29b-41d4-a716-446655440000", "url": "https://nabdcx.com/i/<derived-token>", "status": "sent" }, "request_id": "req_…" }

Zendesk example: ticket closed

When a ticket closes, create a link invitation and put data.url in the ticket reply. Use the ticket id in Idempotency-Key to avoid duplicates on retry; reuse the same key for retries.

curl -X POST https://nabdcx.com/api/public/v1/surveys/550e8400-e29b-41d4-a716-446655440000/invitations   -H "Authorization: Bearer nabd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"   -H "Content-Type: application/json"   -H "Idempotency-Key: zendesk-ticket-1042-closed"   -d '{"contact":{"external_source":"zendesk","external_id":"customer-42","name":"Customer","email":"customer@example.com","language":"en"},"channel":"link","hidden_fields":{"ticket":"1042"},"expires_in_days":30}'

Webhook events

Each event is a POST to your URL with this envelope. Data uses the same ids and shapes as the API.

  • response.completed — A real survey response was completed.
  • feedback.created — A feedback item was created.
  • feedback.analyzed — Nabd AI analysis finished (sentiment, themes, urgency).
  • case.updated — Case status, resolution, assignee or due date changed.
  • alert.triggered — An alert rule fired.
  • invitation.sent — A personal invitation was sent.
  • invitation.failed — Invitation sending failed after allowed attempts.
  • contact.opted_out — A contact opted out of a channel.
  • webhook.test — A test event from the Send test event button.
POST /your-endpoint
X-Nabd-Event: feedback.created
X-Nabd-Event-Id: evt_3c1f…
X-Nabd-Timestamp: 1760630400
X-Nabd-Signature: v1=5d41402abc4b2a76b9719d911017c592…

{
  "event_id": "evt_3c1f…",
  "type": "feedback.created",
  "created_at": "2026-10-16T12:00:00Z",
  "organization_id": "9a2b…",
  "data": { "id": "f_88…", "source": "email", "language": "ar" }
}

Return any 2xx within 10 seconds. Redirects are not followed. We retry up to 8 times (1 minute to 6 hours) and pause the endpoint after 50 consecutive failures. An event can arrive more than once: ignore a repeated event_id.

Verifying signatures

The signature is HMAC-SHA256 with the endpoint secret over timestamp + "." + raw body. Reject timestamps older than 5 minutes. During a secret rotation two signatures are sent for 24 hours.

Node.js

import crypto from "node:crypto";

// raw = the exact request body as a string; secret = your endpoint signing secret
export function verifyNabd(raw, headers, secret) {
  const ts = Number(headers["x-nabd-timestamp"]);
  if (!ts || Math.abs(Date.now() / 1000 - ts) > 300) return false; // older than 5 minutes
  const expected = crypto.createHmac("sha256", secret).update(`${ts}.${raw}`).digest("hex");
  // During a secret rotation the header can carry two values: "v1=…,v1=…"
  return String(headers["x-nabd-signature"] ?? "")
    .split(",")
    .map((s) => s.trim().replace(/^v1=/, ""))
    .some((sig) => sig.length === expected.length &&
      crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected)));
}

Python

import hmac, hashlib, time

def verify_nabd(raw: bytes, headers: dict, secret: str) -> bool:
    ts = int(headers.get("X-Nabd-Timestamp", "0"))
    if not ts or abs(time.time() - ts) > 300:  # older than 5 minutes
        return False
    expected = hmac.new(secret.encode(), f"{ts}.".encode() + raw, hashlib.sha256).hexdigest()
    sigs = [s.strip().removeprefix("v1=") for s in headers.get("X-Nabd-Signature", "").split(",")]
    return any(hmac.compare_digest(s, expected) for s in sigs)

Connect Power BI

Create a read key in Settings › Integrations. In Power BI choose Get Data → Blank Query → Advanced Editor. Add a private text parameter named NabdApiKey, then paste this script. Use Anonymous credentials for the web source because the script sends Authorization. Never share the key or a file containing it.

let
    BaseUrl = "https://nabdcx.com",
    ApiKey = NabdApiKey,
    GetPage = (cursor as nullable text) as record =>
        Json.Document(Web.Contents(BaseUrl, [
            RelativePath = "api/public/v1/export/responses",
            Headers = [Authorization = "Bearer " & ApiKey],
            Query = if cursor = null then [limit = "1000"]
                    else [limit = "1000", cursor = cursor]
        ])),
    Pages = List.Generate(
        () => [Page = GetPage(null), Continue = true],
        each [Continue],
        each if [Page][next_cursor] = null
             then [Page = [data = {}, next_cursor = null], Continue = false]
             else [Page = GetPage([Page][next_cursor]), Continue = true],
        each [Page][data]
    ),
    Result = Table.FromRecords(List.Combine(Pages))
in
    Result

Replace export/responses with export/feedback or metrics/daily as needed. Responses are flat: one row per answer; daily metrics are one row per UTC day/survey. since is inclusive and until exclusive, in ISO format. Scores use your organisation metric definitions.

Excel

Excel: Data → Get Data → From Other Sources → Blank Query, using the same Power Query script. From Web uses Web.Contents with an Authorization header, not a key in the URL. For CSV, request format=csv with header authentication and open the downloaded file using From Text/CSV; a BOM preserves Arabic. Follow X-Next-Cursor for every CSV page.

Google Sheets and Looker Studio

A public CSV URL cannot work because authentication requires a header. In Apps Script store NABD_API_KEY in Script Properties, create a Nabd sheet, and run this script. Connect that sheet to Looker Studio through Google Sheets, or use a trusted JSON connector supporting headers and cursors. Sheet permissions determine who sees the data; do not make it public.

function refreshNabd() {
  const key = PropertiesService.getScriptProperties().getProperty('NABD_API_KEY');
  if (!key) throw new Error('Set NABD_API_KEY in Script Properties');
  const base = 'https://nabdcx.com/api/public/v1/export/responses?limit=1000';
  let cursor = null, rows = [];
  do {
    const response = UrlFetchApp.fetch(base + (cursor ? '&cursor=' + encodeURIComponent(cursor) : ''), {
      headers: {Authorization: 'Bearer ' + key}, muteHttpExceptions: true
    });
    if (response.getResponseCode() !== 200) throw new Error('Nabd HTTP ' + response.getResponseCode());
    const page = JSON.parse(response.getContentText());
    rows = rows.concat(page.data);
    cursor = page.next_cursor;
  } while (cursor);
  const sheet = SpreadsheetApp.getActive().getSheetByName('Nabd');
  if (!sheet) throw new Error('Create a sheet named Nabd');
  sheet.clearContents();
  if (!rows.length) return;
  const columns = Object.keys(rows[0]);
  const safe = value => {
    if (typeof value === 'number') return value;
    const text = value == null ? '' : typeof value === 'object' ? JSON.stringify(value) : String(value);
    return /^[=+@\-\t\r]/.test(text) ? "'" + text : text;
  };
  sheet.getRange(1, 1, rows.length + 1, columns.length).setValues(
    [columns].concat(rows.map(row => columns.map(column => safe(row[column]))))
  );
}

Zapier, Make and n8n

Use generic HTTP/webhook modules; this round has no marketplace app. Test the connection with GET /me using any valid key. Reads need read scope; subscription and deletion need write scope, API access and paid webhook access.

GET /me
POST /hooks
{"target_url":"https://YOUR_WEBHOOK_HOST/path","events":["response.completed"],"description":"Sheets"}
GET /hooks
DELETE /hooks/{id}
GET /hooks/samples/response.completed

POST returns data.id, one-time data.secret, events and created_at. Store the secret securely. Maximum 20 API hooks per org; errors are HOOK_LIMIT, INVALID_TARGET_URL and PLAN_REQUIRED. DELETE returns 204 even if already deleted or outside your org. GET never returns secrets. Samples are static and fake.

Zapier: choose Webhooks by Zapier → Catch Hook, then subscribe its URL with POST /hooks. Use API Request or Custom Request for actions with Authorization: Bearer. An optional Code step can verify HMAC using the raw body and Nabd headers; do not claim verification if those raw inputs are unavailable. Dedupe by event_id.

Make: import the blueprint, create a Custom webhook, then choose your Google Sheets connection, spreadsheet, sheet and column mappings. Use an HTTP module to POST /hooks with the module URL. Replace all placeholders before running; no account connections are embedded.

n8n: import the inactive workflow. For Slack, enable raw body on Webhook; configure NABD_WEBHOOK_SECRET, Slack credentials and channel. Code requires crypto and URL with the built-in module allowed in your trusted environment. Verification never reserializes JSON and rejects timestamps outside five minutes.

Polling template: configure NABD_API_KEY, Google Sheets and the id column. It reads all pages hourly and upserts by id to prevent duplicates. Workflow static data keeps the watermark, committed only after sheet writes succeed. Test in your own environment before activation.

  • Update a CRM contact on an NPS detractor response.
  • Create a ticket on alert.triggered without respondent PII.
  • Log responses to a sheet with deduplication.

Polling and deduplication

GET /responses and /surveys/{id}/responses: completed only by submitted_at; /feedback by created_at; /contacts, /invitations and /surveys/{id}/invitations by updated_at; /alerts by created_at. since is timezone-qualified ISO with an exclusive (>) boundary. Newest first, then descending id on timestamp ties. Follow next_cursor until null; never construct it yourself.

Dedupe: id for responses, feedback and alerts; id + updated_at for contacts and invitations. Multiple changes between polls appear as latest state, not an event history. Capture the poll start watermark before requesting and commit it only after processing every page successfully. Use a small overlap plus deduplication for delayed processing. Alerts omit free-form messages, emails and mobiles.

Helpdesk and CRM connectors

Connect Zendesk, Freshdesk or Zoho Desk to create tickets automatically, or Dynamics 365, Salesforce, Zoho CRM or HubSpot to upsert the contact and log an activity — from Settings › Integrations, no code. Contact identity is sent only when “Share contact details” is on and the response is not anonymous.

Prefer the manual route? Everything the connectors do is available through webhook events (response.completed and alert.triggered) or the API, and through Zapier, Make and n8n as in the automation section.

Credentials: helpdesks

  • Zendesk — account email + API token: Admin Center › Channels › API › API tokens. Base URL https://<subdomain>.zendesk.com.
  • Freshdesk — API key: profile picture › Profile settings › API key. Base URL https://<subdomain>.freshdesk.com.
  • Zoho Desk — self client in the Zoho API Console (api-console.zoho.com) with scopes Desk.tickets.CREATE and Desk.contacts.READ, then a refresh token + client id/secret + data centre. Base URL https://desk.zoho.<dc>.

Credentials: CRMs

  • HubSpot — private app: Settings › Integrations › Private Apps, with crm.objects.contacts and crm.objects.notes scopes. Fixed base URL https://api.hubapi.com.
  • Salesforce — Connected App with the Client Credentials flow and the api scope; base URL https://<your>.my.salesforce.com, tokens are managed automatically via login.salesforce.com.
  • Zoho CRM — self client with scopes ZohoCRM.modules.contacts.CREATE and ZohoCRM.modules.tasks.CREATE; base URL https://www.zohoapis.<dc>.
  • Dynamics 365 — Entra app registration with Client Credentials, then an application user in Power Platform with a role that writes contacts and tasks; base URL https://<org>.crm4.dynamics.com.

Short-lived tokens (Zoho, Salesforce, Dynamics) refresh automatically when they expire; no manual renewal needed.

Incoming triggers — configuration guide

One generic mechanism, without tool-specific connectors. Invitations keep Nabd’s existing consent, send-window and daily-cap rules. Link invitations do not send a message or delay link creation. WhatsApp is currently disabled.

POST https://nabdcx.com/api/public/inbound/<public_id>
Authorization: Bearer <source-secret>
Content-Type: application/json

{"event_id":"fake-delivery-42","customer":{"name":"Example","mobile":"+966500000042","email":"example@example.invalid"},"data":{"order":{"id":"fake-42"}}}

HMAC: default X-Signature header containing hex HMAC-SHA256(secret, raw_body), optionally prefixed sha256=. URL secret: ?secret=<source-secret>. Each source uses one mode only. 256 KB, 120 requests/minute; event IDs deduplicate for 30 days. 202 accepted/skipped, 200 duplicate. Raw bodies are never stored.

Salla — configuration guide

Select an order-completed or status-updated event in the webhook registration available to your app/store. POST targets and configurable headers depend on the app type. Use Bearer when Authorization can be set, or middleware generating Nabd-compatible HMAC; do not assume Salla’s native signature matches this contract.

Field names vary by account and edition. Check a sample in the local test box before activation. This illustrative mapping is not the tool’s official payload contract.

{
  "event_id_path": "event_id",
  "field_mapping": {
    "name": "customer.name",
    "mobile": "customer.mobile",
    "email": "customer.email",
    "external_id": "customer.id",
    "reference": "data.order.id",
    "metadata": {
      "item": "items[0].name"
    }
  }
}

API alternative: POST /api/public/v1/surveys/{survey_id}/invitations with a write-scoped API key, contact or contact_id, channel and send_at. There is no standalone POST /v1/invitations; use the survey-scoped endpoint.

Reference: https://docs.salla.dev/webhooks

Zid — configuration guide

Register a supported order event. Zid’s documented Basic authentication is not Bearer and is not directly supported by Nabd. Use a URL secret if query parameters are accepted; otherwise transform authentication through Make or n8n.

Field names vary by account and edition. Check a sample in the local test box before activation. This illustrative mapping is not the tool’s official payload contract.

{
  "event_id_path": "event_id",
  "field_mapping": {
    "name": "customer.name",
    "mobile": "customer.mobile",
    "email": "customer.email",
    "external_id": "customer.id",
    "reference": "data.order.id",
    "metadata": {
      "item": "items[0].name"
    }
  }
}

API alternative: POST /api/public/v1/surveys/{survey_id}/invitations with a write-scoped API key, contact or contact_id, channel and send_at. There is no standalone POST /v1/invitations; use the survey-scoped endpoint.

Reference: https://docs.zid.sa/webhooks

Foodics — configuration guide

Use order closure only when supported by your Foodics partner/account. Self-service outbound webhook availability is not established for every account; use a partner integration or API middleware, then send Bearer to Nabd.

Field names vary by account and edition. Check a sample in the local test box before activation. This illustrative mapping is not the tool’s official payload contract.

{
  "event_id_path": "event_id",
  "field_mapping": {
    "name": "customer.name",
    "mobile": "customer.mobile",
    "email": "customer.email",
    "external_id": "customer.id",
    "reference": "data.order.id",
    "metadata": {
      "item": "items[0].name"
    }
  }
}

API alternative: POST /api/public/v1/surveys/{survey_id}/invitations with a write-scoped API key, contact or contact_id, channel and send_at. There is no standalone POST /v1/invitations; use the survey-scoped endpoint.

Reference: https://apidocs.foodics.com/

Genesys Cloud — configuration guide

For call completion use conversation notifications or a licensed workflow/data action plus middleware detecting completion and sending Bearer. Open Messaging is not a general call-ended event; Webhook for Events receives into Genesys rather than sending to Nabd.

Field names vary by account and edition. Check a sample in the local test box before activation. This illustrative mapping is not the tool’s official payload contract.

{
  "event_id_path": "event_id",
  "field_mapping": {
    "name": "customer.name",
    "mobile": "customer.mobile",
    "email": "customer.email",
    "external_id": "customer.id",
    "reference": "data.order.id",
    "metadata": {
      "item": "items[0].name"
    }
  }
}

API alternative: POST /api/public/v1/surveys/{survey_id}/invitations with a write-scoped API key, contact or contact_id, channel and send_at. There is no standalone POST /v1/invitations; use the survey-scoped endpoint.

Reference: https://help.genesys.cloud/articles/about-webhook-for-events/

Avaya — configuration guide

For Avaya Infinity verify available subscription events and delivery-token format; subscriptions may require renewal. Do not generalise to every Avaya product. Use middleware translating an interaction-ended event to Bearer if native authentication is incompatible.

Field names vary by account and edition. Check a sample in the local test box before activation. This illustrative mapping is not the tool’s official payload contract.

{
  "event_id_path": "event_id",
  "field_mapping": {
    "name": "customer.name",
    "mobile": "customer.mobile",
    "email": "customer.email",
    "external_id": "customer.id",
    "reference": "data.order.id",
    "metadata": {
      "item": "items[0].name"
    }
  }
}

API alternative: POST /api/public/v1/surveys/{survey_id}/invitations with a write-scoped API key, contact or contact_id, channel and send_at. There is no standalone POST /v1/invitations; use the survey-scoped endpoint.

Reference: https://developers.avayacloud.com/avaya-infinity/reference/subscribe

ServiceNow — configuration guide

Use a case-resolved workflow with an outbound REST request and Authorization: Bearer. Integration Hub REST steps depend on subscription and permissions. A REST API trigger receives into ServiceNow and is not the required outgoing mechanism.

Field names vary by account and edition. Check a sample in the local test box before activation. This illustrative mapping is not the tool’s official payload contract.

{
  "event_id_path": "event_id",
  "field_mapping": {
    "name": "customer.name",
    "mobile": "customer.mobile",
    "email": "customer.email",
    "external_id": "customer.id",
    "reference": "data.order.id",
    "metadata": {
      "item": "items[0].name"
    }
  }
}

API alternative: POST /api/public/v1/surveys/{survey_id}/invitations with a write-scoped API key, contact or contact_id, channel and send_at. There is no standalone POST /v1/invitations; use the survey-scoped endpoint.

Reference: https://www.servicenow.com/docs/r/integrate-applications/integration-hub/rest-request-action-designer.html

SAP — configuration guide

Identify the SAP product first. Route an order-delivered event through Event Mesh or Integration Suite according to edition to middleware/HTTP. Verify event schema/auth; send Bearer from middleware rather than assuming a universal SAP webhook.

Field names vary by account and edition. Check a sample in the local test box before activation. This illustrative mapping is not the tool’s official payload contract.

{
  "event_id_path": "event_id",
  "field_mapping": {
    "name": "customer.name",
    "mobile": "customer.mobile",
    "email": "customer.email",
    "external_id": "customer.id",
    "reference": "data.order.id",
    "metadata": {
      "item": "items[0].name"
    }
  }
}

API alternative: POST /api/public/v1/surveys/{survey_id}/invitations with a write-scoped API key, contact or contact_id, channel and send_at. There is no standalone POST /v1/invitations; use the survey-scoped endpoint.

Reference: https://community.sap.com/t5/technology-blog-posts-by-sap/when-to-use-event-mesh-webhook/ba-p/13535830

Oracle — configuration guide

Choose the Oracle product and event, such as service completion. OCI Notifications has subscription confirmation and its own signing contract, not handled directly by this endpoint; use Oracle Integration or middleware sending Bearer. Content Management webhooks do not imply support in every Oracle product.

Field names vary by account and edition. Check a sample in the local test box before activation. This illustrative mapping is not the tool’s official payload contract.

{
  "event_id_path": "event_id",
  "field_mapping": {
    "name": "customer.name",
    "mobile": "customer.mobile",
    "email": "customer.email",
    "external_id": "customer.id",
    "reference": "data.order.id",
    "metadata": {
      "item": "items[0].name"
    }
  }
}

API alternative: POST /api/public/v1/surveys/{survey_id}/invitations with a write-scoped API key, contact or contact_id, channel and send_at. There is no standalone POST /v1/invitations; use the survey-scoped endpoint.

Reference: https://docs.oracle.com/en-us/iaas/Content/Notification/Concepts/notificationoverview.htm

Generic — configuration guide

Send a stable-ID event with HTTPS POST from a tool supporting custom requests. Choose URL secret, Bearer or HMAC over the raw body. If native outgoing webhooks are unavailable use Zapier, Make, n8n or the invitations API.

Field names vary by account and edition. Check a sample in the local test box before activation. This illustrative mapping is not the tool’s official payload contract.

{
  "event_id_path": "event_id",
  "field_mapping": {
    "name": "customer.name",
    "mobile": "customer.mobile",
    "email": "customer.email",
    "external_id": "customer.id",
    "reference": "data.order.id",
    "metadata": {
      "item": "items[0].name"
    }
  }
}

API alternative: POST /api/public/v1/surveys/{survey_id}/invitations with a write-scoped API key, contact or contact_id, channel and send_at. There is no standalone POST /v1/invitations; use the survey-scoped endpoint.

Start with Nabd today.

Built to empower CX teams in Saudi Arabia: design, measurement and improvement tools that understand local context and speak your customer's language.