01What is the YallaBuy node for n8n?
The package is named n8n-nodes-yallabuy and installs two nodes into your workspace:
- The YallaBuy action node: a full gateway to the Public API v1 — 19 resources and 80 operations: read and write across orders, products, inventory, customers, returns and refunds, marketing, reports, restaurant and security. Every request rides a ybapi_ key as a Bearer header, and the node shapes fields and names to the API laws for you.
- The YallaBuy Trigger node: receives signed webhook deliveries straight into your n8n workspace — it verifies the HMAC signature itself, deduplicates retries, filters to the event types you select, and emits each event as a workflow item. Without writing a single line of receiver code.
Everything documented on this page is derived from the platform's actual contract: the same pagination, scope and rate-limit laws the API enforces, and the same signature scheme the sender signs with. What you read here is what happens in production.
02Installation
- The package runs on self-hosted n8n (the community nodes contract). In the n8n UI: open "Settings" then "Community nodes" and press "Install".
- Enter the package name: n8n-nodes-yallabuy, and accept the community-package warning.
- Wait for installation. For a manual npm install, use the commands below inside the n8n runtime environment, then restart your instance.
- After installation you will find "YallaBuy" and "YallaBuy Trigger" in the node panel under integrations — search for YallaBuy in the node picker.
mkdir -p ~/.n8n/nodes
cd ~/.n8n/nodes
# Only if package.json does not exist yet:
npm init -y
npm install n8n-nodes-yallabuy
# Restart your n8n instance using your deployment manager.03Connecting your account — credentials
Set up the credential once (Credentials → New → YallaBuy API). Four simple fields:
| Field | Value | Where to get it |
|---|---|---|
| Base URL | https://yallabuy.app (default) — change only for a dedicated environment | Fixed |
| API Key | A key starting with ybapi_ | Dashboard → Settings → API keys (/dashboard/settings/integrations/api) |
| Webhook Signing Secret | The endpoint secret — starts with whsec_, shown once at endpoint creation | Dashboard → Settings → Webhooks |
| Previous Webhook Signing Secret | Optional — the old secret during a rotation (24-hour overlap window) | The same webhooks screen, when rotating |
On save, n8n verifies the connection automatically with a GET to /api/v1 — a working key shows a success mark; a broken one shows the API's actual error code.
04The YallaBuy node — 19 resources, 80 operations
Pick a resource, then an operation — the parameter panel adapts to the chosen operation automatically. Here is the full map:
| Resource | Operations |
|---|---|
| Store | getProfile · getSettings · getFeatures · getSetup · getBuilderContext · getDesignContext |
| Product | create · get · getMany · update · archive · getManySerials |
| Order | create · get · getMany · updateStatus · dispatch · decideCancellation · advanceKitchen · transferTable · releaseTable |
| Customer | create · get360 · getMany · update · delete |
| Inventory | getMany · getOverview · getItem · getMovements · receive · adjust · bulkPreview · bulkApply |
| Return | create · get · getMany · getManyRequests · review · refundApproval · refundExecution |
| Coupon | create · getMany · update · delete |
| Promotion | create · getMany · getPerformance · update · delete |
| Bundle | create · update · delete |
| Marketing | getOverview |
| Analytics | sales · productPerformance · insights · overview · actionCenter · profitLoss · expenses |
| Shift | getMany · get |
| Staff | getMany · get |
| Branch | getMany |
| Restaurant | floorPlan · kds · kitchenConfig |
| Search | searchEverything |
| Activity | getMany |
| Security | loginHistory · staffActivity · securityActivity |
| Store Design | getContext · propose · preview · diff · verify · apply |
Operating rules that matter — all of them are the API's own laws, enforced by the node on your behalf:
- Pagination: any list operation exposes "Return All" — it follows the opaque cursor across every page, re-sending filters on each request because the server re-authorizes per page. Without Return All, use "Limit" from 1 to 50.
- Idempotency: keyed operations accept an Idempotency-Key. Supply a durably stored UUID for retries of the same operation; leaving it blank generates a new key per item. Read the retry guidance below before running write automations.
- Order creation: prices are re-derived from your catalog by the platform (any price sent in the payload is ignored), the channel is website only, items run 1–200 — and variant_id is required for multi-variant items.
- Dynamic pickers: fields like product, customer, branch or table populate from your actual account — a dropdown sourcing the API.
- Errors: any API rejection surfaces with its real identity — the stable code (such as SCOPE_INSUFFICIENT) plus the request_id so support can trace it. With "Continue On Fail" the node emits an error item and the workflow continues instead of stopping.
05The YallaBuy Trigger node — receiving signed events
The trigger receives webhook deliveries on your n8n URL and applies the exact receiving laws documented in the webhooks guide. Registration is manual by contract — endpoint management is dashboard-only, with no registration API:
- Place a "YallaBuy Trigger" in your workflow and activate it — copy the PRODUCTION URL shown above the canvas. The URL must be public HTTPS on port 443 or 8443 (the same security law — dev tunnels like ngrok work with the port condition).
- In the dashboard: Settings → Webhooks (/dashboard/settings/integrations/webhooks) → create an endpoint with that URL, subscribing to the SAME event types you select in the node.
- Copy the one-time secret (whsec_) into the credential (Webhook Signing Secret field). If you rotate the secret, put the old one in the Previous field — the trigger tries both during the overlap.
- Press "Send test event" on the webhooks screen — within about a minute a signed ping reaches your URL and the delivery shows DELIVERED in the dashboard.
Every arriving delivery goes through this check sequence before any workflow run:
- All six headers present? Missing ones are answered 401 immediately — no workflow run.
- Signature: v1=<hex> computed as HMAC-SHA256 over ${timestamp}.${endpoint_id}.${event_id}.${delivery_id}.${body} — constant-time compare with a ±300-second freshness window. A broken signature or stale timestamp = 401.
- Deduplication remembers webhook-delivery-id for one hour per n8n instance. This is not an exactly-once guarantee across instances or after expiry; durably deduplicate your workflow’s side effects.
- Filter: an event outside the selected types (with "Listen to All Events" off) answers 200 without a run — accepted, simply not relevant to you.
When an event passes the checks, it emits one output item carrying the payload exactly as sent, plus four header echoes for workflow routing: webhook_event_type, webhook_delivery_id, webhook_event_id and webhook_endpoint_id.
06All events — the 16 subscribable types
These are the types you can select in the trigger (the same catalog you subscribe to in the dashboard — the two must match). Each type also has its own full-payload page in the webhooks guide at /developers/webhooks:
| Type | Fires when | What you receive |
|---|---|---|
| order.created | A new order is placed (storefront/POS/API) | The full order: items, totals, customer, payment — first generation (flat fields alongside the envelope) |
| order.status_changed | An order moves status (confirm → prepare → ship → deliver…) | The order with its old and new status — first generation |
| order.cancellation_requested | A cancellation is requested for an order | The order, the cancellation reason and review state |
| order.cancellation_decided | A cancellation decision is made (approve or reject) | The decision, its reason, and the order after it |
| return.created | An actual return is recorded for an order | The returned items and amounts |
| return.requested | A customer requests a return | The order and the items requested for return |
| return.request_decided | A return request decision is made | The decision and its reason |
| refund.executed | An approved refund is actually executed | The amount, refund method and external reference |
| product.created | A new product is published | The product's core data |
| product.updated | Any change to an existing product | The product after the change |
| product.deleted | A product is deleted | The deleted product's id |
| inventory.received | A stock receipt arrives | The item, received quantity and cost |
| inventory.adjusted | Any stock adjustment (shortage/surplus/damage) | The item, quantity and reason |
| coupon.redeemed | A coupon is redeemed on an order | The coupon code, discount, order and customer |
| kitchen.status_changed | A kitchen item changes state | The item and its new status (QUEUED/IN_PREP/READY/SERVED) |
| shift.closed | A register shift is closed | The shift totals and summary |
The unified payload shape — a fixed envelope (id, type, api_version, tenant_id) with the event details inside. A live example:
{
"id": "mwh:coupon-redeemed:9e8d7c6b-5a4f-4e3d-2c1b-0a9f8e7d6c5b:b7c8d9e0-1f2a-4b3c-9d4e-5f6a7b8c9d0e",
"type": "coupon.redeemed",
"api_version": "v2",
"tenant_id": "9e8d7c6b-5a4f-4e3d-2c1b-0a9f8e7d6c5b",
"data": {
"redemption_id": "b7c8d9e0-1f2a-4b3c-9d4e-5f6a7b8c9d0e",
"coupon_id": "0a9b8c7d-6e5f-4a3b-8c2d-1e0f9a8b7c6d",
"coupon_code": "WELCOME10",
"order_id": "3f0c8e6a-1d24-4b7f-9a3e-2c5b8d90f1aa",
"receipt_number": "RCP-20261020-1482",
"customer_phone": "+201001234567",
"customer_id": "3a4b5c6d-7e8f-4a9b-8c0d-1e2f3a4b5c6d",
"discount_amount": 50,
"redeemed_at": "2026-10-20T12:34:56.812450+00:00"
}
}Two payload notes: the three first-generation types (order.created, order.status_changed, return.created) carry their fields flat next to the envelope rather than inside data — as first-integration compatibility requires. And the payload laws are constant for all types: a 64 KB cap, items truncated at 100 with the items_truncated flag, and cost (COGS) data always stripped.
07Ready workflow patterns
Three patterns cover most use cases — all starting from these two nodes:
- Real-time order notifications: YallaBuy Trigger (order.created) → YallaBuy/get for extra details → Telegram, Email or Slack with the order number, total and address.
- Cancellation autopilot: YallaBuy Trigger (order.cancellation_requested) → an IF node on order value or reason → YallaBuy/order decideCancellation (approve/reject) → log the decision to Google Sheets.
- Hourly compensating sync: Schedule Trigger → YallaBuy/order getMany with an updated_since filter → upsert into your database or Sheets — a safety net under the webhooks in case any delivery slips.
08Limits and rules
The Public API enforces rate limits across five classes — a 429 comes back with a Retry-After header telling you how long to wait:
| Class | Limit | Covers |
|---|---|---|
| Standard read | 60 req/min | Most lists and reads |
| Heavy read | 20 req/min | Reports and aggregated analytics |
| Mutation | 20 req/min | Create and update operations |
| High-risk | 10 req/min | Inventory, order and storefront writes (scopes enabled on the keys screen) |
| Bulk write | 5 req/min | Bulk inventory operations |
- Any write request body: 64 KB maximum.
- Forbidden fields (attribution, actor_id and the like) reject the request rather than being stripped — the node never sends them in the first place.
- Persist a stable UUID and unchanged payload for retries of the same keyed operation. Never reuse a key for a new operation or changed payload; replay semantics depend on the authority. Leaving the field empty generates a fresh key per item, so rerunning a workflow may create a new operation.
- Grouped multi-store reads (such as the inventory overview) come back grouped per store — the node returns them verbatim without flattening.
09Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Trigger answers 401 INVALID_SIGNATURE | The secret in n8n does not match the endpoint (or was rotated) | Update the Webhook Signing Secret in the credential, and put the old one in Previous |
| 401 UNAUTHENTICATED from the action node | Wrong or revoked ybapi_ key | Mint a new key on the API keys screen |
| 403 SCOPE_INSUFFICIENT | The key was not minted with the required scope | Enable the scope on the keys screen — high-risk ones need their explicit opt-in |
| replayed: true or 409 CONFLICT | An Idempotency-Key was used previously | Keep the same key only for the same operation and payload. Use a new key for a genuinely new operation, not merely after a network failure. |
| 409 INVALID_STATE_TRANSITION | The operation is not allowed from the order's current state | Pull the order with get and check its actual status first |
| 429 RATE_LIMITED | The class rate limit was exceeded | Respect Retry-After or reduce request frequency |
| 503 API_DISABLED | The Public API is disabled on this deployment | Contact the deployment administrator. Replacing a token or changing node settings does not enable the API. |
| No workflow runs at all | The endpoint is not ACTIVE or the workflow is not activated in n8n | Activate the workflow (the test URL serves a single test only) and check the webhooks screen |
One special case: a ping arrived and nothing ran — that is not a failure, that is the filter working (the test event is not among the selected types). See the trigger section's note above.
COMPLETE YOUR INTEGRATION
