Ways to integrate
Approach is a Kuwait marketplace for services, shops, food, tickets, travel and Premium. You can connect in any of the ways below. API methods need a key from us; link and feed methods work with no key at all.
| Method | Who it is for | What it does | Status | How to start |
|---|---|---|---|---|
| Premium provisioning API | Telecom operators, banks, employers, loyalty programs | Turn Approach Premium on or off for your customers by Kuwait mobile number. Billed to you monthly. | Live | API key |
| Availability sync API | Businesses on Approach with their own booking calendar | Push your closed days to Approach so customers cannot book them. | Live | API key bound to your business |
| Order webhooks | Businesses on Approach with their own system | Approach posts signed order.paid, order.cancelled and order.updated events to your server. |
Live | Send us your https URL |
| Digital supplier contract | eSIM, voucher, booking code and policy suppliers | Approach reads your catalogue, places orders on your API and receives your delivery webhooks. | Live | Share your API docs and a key |
| Code stock files | Suppliers without an API | Hand us a CSV of codes; each paid order takes the next code automatically. | Live | Send a CSV |
| Store catalogue sync | Online stores on Shopify, WooCommerce, MNASATI or Bilbayt | Your website's products are pulled into Approach and their prices and stock kept in step. | Live | Send us your store address |
| Assisted onboarding | Any business | Send a menu, price list or spreadsheet with photos; our team builds your catalogue. | Live | Contact us |
| Links and deep links | Websites, apps, marketing teams | Link to any business, product, package or landing page. Phones with the app open it in the app. | Live | No key needed |
| Referral tag | Partner websites sending customers to Approach | Order links that carry your ref code, so the orders that follow are counted for you. |
On request | Ask for a code |
| Product feeds, sitemap, structured data | Search engines, comparison sites, aggregators | Public product feeds in Google Merchant format, an XML sitemap and schema.org data on every page. | Live | No key needed |
| Payment links | Businesses selling outside the app | A branded link for any amount; the customer pays by KNET, card or Apple Pay. | On request | Contact us |
| Web checkout | Customers without the app | Shops and services can be ordered and paid on tryapproach.net with no app and no login. | Live | Nothing to set up |
| Business app and dashboard | Every business on Approach | Accept orders, manage packages and calendars, get push and WhatsApp alerts, read reports. | Live | Apply as a business |
| Visa providers and event organizers | Visa offices, clubs, venues | Receive visa applications with travellers' documents; sell tickets and scan them at the gate. | Live | Contact us |
Get API keys
This page is public; your credentials are not. Each partner gets its own key (and, for webhooks, its own signing secret), issued privately and shown to you once. Tell us which method you need, your company name, your technical contact, and, if you want it, the list of server IP addresses your calls will come from.
Get API keys: [email protected] · +965 9000 3470 (calls and WhatsApp)
Base URL and conventions
Partner API calls go over HTTPS to:
https://api.tryapproach.net- Every path below is relative to this base. There is no
/apior version prefix. - Request and response bodies are JSON. Send
Content-Type: application/jsonon POST and PUT. - Money is in Kuwaiti dinars (
KWD, three decimals). Times are ISO 8601. Calendar dates are Kuwait dates writtenYYYY-MM-DDwith no time zone. - Every JSON response carries
success(true or false). Treat it as the source of truth.
Authentication
Send your secret key in the X-Api-Key header on every request. We store only a hash of it, so we
cannot show it to you again; if it is lost we rotate it and the old key stops working at once.
X-Api-Key: apk_your_secret_key_here
Your key can be locked to a fixed list of server IP addresses. When
that is on, a call from any other address is refused with 403.
A key belongs to one of two kinds of partner. A subscription partner (for example a telecom operator) uses the Premium endpoints. A business partner is bound to one business on Approach and uses the availability endpoints and order webhooks. A key only ever sees its own data.
Errors
Errors use normal HTTP status codes and a JSON body with success: false, a readable
message, and the HTTP status repeated as a number in status. Premium endpoints also add a
machine readable code (see result codes).
{
"success": false,
"message": "Invalid API key",
"status": 401
}| Status | When |
|---|---|
| 200 | Success, including safe repeats such as ALREADY_ACTIVE. |
| 400 | Bad input: an invalid phone number, a missing field, a bad date, an unknown package. |
| 401 | Missing API key or Invalid API key (unknown, rotated or switched off). |
| 403 | IP not allowed, or the key is not bound to a business for an availability call. |
| 404 | Nothing matches, for example cancelling an unknown reference. |
| 5xx | A temporary problem on our side. Retry with backoff. |
Limits and retries
- Keep to a steady rate, batch where the API allows (the availability sync takes a full year of dates in one call), and expect a limit to be agreed for high volume.
- Retry
5xx,429and network timeouts with exponential backoff. Do not retry other4xxanswers unchanged; fix the request first. - Activation and the availability sync are idempotent, so a retry after an unclear network error is always safe.
- Webhooks we receive from suppliers are flood guarded per sender IP; a
429answer carries aRetry-Afterheader in seconds.
Availability sync
For a business on Approach that runs its own booking calendar. Your system tells Approach which days are closed; the Approach app then greys those days out and refuses orders for them. Your key is bound to your business, so you can only ever read and write your own calendars. Days that our team or you close by hand in Approach are never touched by the API.
The packages you can sync: each bookable package of your business that has a calendar.
{
"success": true,
"data": {
"businessUserId": 900001,
"packages": [
{ "packageId": 77001, "settingId": 4101, "serviceId": 8, "categoryId": 62,
"title": "Breakfast tray for 10", "titleAr": "صينية فطور لعشرة أشخاص" }
]
}
}Closed days from today on, per package. source is api for days you set through the
API and manual for days closed by hand in Approach.
{
"success": true,
"data": { "packages": [
{ "packageId": 77001, "closedDates": [
{ "date": "2026-11-20", "source": "api" },
{ "date": "2026-11-27", "source": "manual" }
] }
] }
}Send the full list of closed days every time. Days in the list are closed; days you set before and leave out are opened again. Past days are ignored. Repeating the same call changes nothing.
| Field | Type | Required | Description |
|---|---|---|---|
dates | string[] | required | Kuwait dates as YYYY-MM-DD, at most 366. An empty list opens every day you closed. |
packageIds | integer[] | optional | Only these packages. Leave it out to apply the list to all your packages. |
curl -X PUT https://api.tryapproach.net/partners/availability/dates \ -H "X-Api-Key: apk_your_secret_key_here" \ -H "Content-Type: application/json" \ -d '{ "dates": ["2026-11-20", "2026-11-21"], "packageIds": [77001] }'
{
"success": true,
"message": "Availability synced",
"data": {
"packagesUpdated": [77001],
"closedDates": ["2026-11-20", "2026-11-21"],
"overridesCreated": 2,
"overridesRemoved": 0
}
}Errors: 400 for a date that is not YYYY-MM-DD, more than 366 dates, an empty
packageIds list or a package that is not yours; 403 when the key is not bound to a business.
Order webhooks
For a business partner with its own system. When one of your orders is paid, cancelled after payment, or has its date or time changed, Approach posts a signed JSON event to your https URL. You only ever hear about money that landed: unpaid orders are never sent.
| Event | When | event_id |
|---|---|---|
| order.paid | The customer paid the order. | evt_paid_{orderId} |
| order.cancelled | A paid order was cancelled or rejected (refunds included). | evt_cancelled_{orderId} |
| order.updated | A paid order's date or time was changed. | evt_updated_{orderId}_{unixTime} |
Request
Content-Type: application/json X-Approach-Event: order.paid X-Approach-Event-Id: evt_paid_48213 X-Approach-Timestamp: 1793865164 X-Approach-Signature: sha256=5f0c9a...e41b
{
"event": "order.paid",
"event_id": "evt_paid_48213",
"payloadVersion": 2,
"orderId": 48213,
"businessUserId": 900001,
"serviceId": 8,
"packageId": 77001,
"date": "2026-11-20",
"time": "18:00",
"customer": { "name": "Sara", "phone": "96550123456", "email": "[email protected]" },
"address": { "governorate": "Hawalli", "area": "Salmiya", "areaId": 12, "block": "4",
"street": "Salem Al Mubarak", "addressLine": "Salmiya, block 4, Salem Al Mubarak" },
"options": [ { "labelEn": "Extra persons", "labelAr": "عدد الأشخاص", "valueEn": null, "valueAr": null, "count": 5 } ],
"extraGuests": 5,
"totalAmount": 185.5,
"currency": "KWD",
"occurredAt": "2026-11-05T09:12:44.120Z"
}date (YYYY-MM-DD), time (HH:mm, 24 hour, Kuwait time),
packageId, address and totalAmount are filled for package bookings and are
null when an order type does not have them. Any detail we cannot read is sent as null
rather than holding the event back.
Verify the signature
The signature is the hex HMAC SHA256 of timestamp + "." + rawBody with your signing secret. It is
computed fresh on every attempt. Reject events whose timestamp is more than a few minutes old.
const crypto = require("crypto"); function verifyApproach(headers, rawBody, secret) { const ts = headers["x-approach-timestamp"]; const got = String(headers["x-approach-signature"] || "").replace(/^sha256=/, ""); if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false; const want = crypto.createHmac("sha256", secret).update(ts + "." + rawBody).digest("hex"); return got.length === want.length && crypto.timingSafeEqual(Buffer.from(got), Buffer.from(want)); }
Answering and retries
- Answer any
2xxwithin 10 seconds to accept the event. 429,5xx, timeouts and network errors are retried: up to 6 attempts with exponential backoff starting at 60 seconds.- Any other
4xx(for example409or422) is treated as your final answer and is not retried. - Redirects are not followed, so give us the exact final URL.
- The same occurrence keeps the same
event_idacross retries. Store it and answer repeats with the result you gave the first time.
Digital product suppliers
For suppliers of eSIMs, vouchers, booking codes or insurance policies. This contract runs the other way: you host the API and Approach calls it. When a customer pays, Approach places the order on your API and delivers the result (QR code, activation code, file) to the customer in the app, by e-mail and on a delivery page. If your API already exists in another shape, send us its documentation; we build an adapter for well known platforms instead of asking you to change.
Approach sends your key as Authorization: Bearer <key>, with JSON bodies, and waits up to 12
seconds per call. We call a sandbox base URL first and switch to your live base URL after a test order.
| Your endpoint | Approach uses it to |
|---|---|
| GET /packages | Read your catalogue (on a schedule, to keep costs in step). |
| POST /orders | Buy one unit after the customer paid. |
| GET /orders/{ref} | Read the state of an order. |
| POST /orders/{ref}/cancel | Cancel an order and learn whether it was refunded. |
{ "data": [
{ "sku": "TR-7D-5GB", "name": "Turkey 5 GB, 7 days", "countries": ["TR"],
"data_mb": 5120, "validity_days": 7, "cost": 3.250, "currency": "KWD", "retail": 4.500 }
] }{
"sku": "TR-7D-5GB",
"qty": 1,
"idempotency_key": "a91c3e0f7b...",
"customer_ref": "48213-1",
"email": "[email protected]",
"start_date": "2026-12-01",
"end_date": "2026-12-08",
"destination_country": "TR",
"documents": [ { "kind": "passport", "url": "https://..." } ]
}start_date and end_date are sent when the order carries trip dates, and
destination_country (ISO 3166 alpha 2) when known. documents (passport,
civil_id) is sent only to suppliers who need them, as signed links valid for at most 24 hours.
{ "data": {
"status": "ready",
"ref": "ORD-991",
"lpa": "LPA:1$smdp.example.com$ABC123",
"activation_code": "ABC123",
"smdp_address": "smdp.example.com",
"iccid": "8990000000000000001",
"confirmation_code": null,
"file_url": null,
"install_url": "https://..."
} }- Answer
"status": "pending"when delivery takes time, then sendorder.completedto our webhook. - You must treat
idempotency_keyas unique: a repeated key returns the first order and never buys twice. We retry after timeouts and5xx, so this is what keeps a customer from being charged twice by you. - Answer
429or5xxfor temporary problems (we retry) and other4xxfor a final no. GET /orders/{ref}answers{ "data": { "status", "activation_status", "usage_mb" } }; cancel answers{ "refunded": true }orfalse.
Supplier webhooks to Approach
We give you a webhook URL that ends in /webhooks/digital/{partnerKey} and a shared signing secret.
Send X-Timestamp (unix seconds) and X-Signature, the hex HMAC SHA256 of
timestamp + "." + rawBody (a sha256= prefix is accepted). Events older than 5 minutes are
refused. A GET or HEAD on the URL answers 200 for your opt in check.
{
"id": "evt_10023",
"type": "order.completed",
"data": { "ref": "ORD-991", "lpa": "LPA:1$smdp.example.com$ABC123", "iccid": "8990000000000000001",
"install_url": "https://...", "install_url_android": "https://..." }
}| type | Effect in Approach |
|---|---|
| order.completed | A pending order is delivered to the customer (fields as in the order answer). |
| order.failed | The order is marked failed and the customer's money is handled by Approach. |
| esim.installed · esim.activated · esim.expired | The eSIM state shown to the customer is updated. |
| usage.updated · usage.threshold | Data used is updated from data.usage_mb. |
| usage.low | The customer gets one low data notice. |
| esim.expiring | The customer gets one expiry notice. |
| Our answer | Meaning |
|---|---|
| 200 { "ok": true } | Applied. "duplicate": true means we had this id already. |
| 401 | Bad or missing signature, or an old timestamp. |
| 400 | The body is not valid JSON. |
| 409 { "code": "unknown_ref" } | We do not know this ref yet. Retry shortly. |
| 503 | Temporary. Retry. |
Code stock files
No API? Give us your codes as a CSV file (UTF 8, up to 5,000 rows and 2 MB per file). Each paid order takes the next free code and delivers it at once. The header row names the columns you use:
lpa,activation_code,smdp_address,confirmation_code,iccid LPA:1$smdp.example.com$ABC123,ABC123,smdp.example.com,,8990000000000000001 ,,,VOUCHER-7781,
A supplier can also fill each order by hand: the order waits until the code or file is uploaded, then the customer is notified.
Store catalogue sync
For online stores. Give us your store's website and we read its public product list. Supported today: Shopify, WooCommerce, MNASATI and Bilbayt.
- Auto pull brings in products that are not on Approach yet: name (Arabic too when your site has it), description, price, crossed out price, stock and up to 5 photos. New products wait hidden for review unless you ask for them to go live straight away.
- Auto sync keeps price, sale price and stock in step on a schedule you choose (every 24, 48, 72 hours or weekly). It never deletes or hides products and never changes photos or names.
- Safety holds: if your site answer looks wrong (unreachable, much smaller than before, or a price moving below 30% or above 3 times its value), nothing changes for that run.
- Products whose sizes have different prices are added by hand.
Assisted onboarding
Not on one of those platforms? Send us your menu, price list or spreadsheet with photos. Our team builds your catalogue on Approach, including options and add ons, and you preview it before it goes live.
Links and deep links
Every public Approach page has a stable link you can put on your site, in an e-mail or in an ad. On phones that have the Approach app, supported links open straight in the app (iOS Universal Links, Android App Links); everyone else gets the web page or the download page.
| Link | Opens |
|---|---|
| https://tryapproach.net/@{handle} | A business profile (handle as shown in the app). |
| https://tryapproach.net/{ar|en}/p/{productId} | A shop product page. |
| https://tryapproach.net/{ar|en}/c/{categoryId} | A category with all its businesses. |
| https://tryapproach.net/{ar|en}/rmp/{id} | A Premium Exclusive package. |
| https://tryapproach.net/{ar|en}/travel | Travel: shops, transfers, eSIMs and visas. |
| https://tryapproach.net/{ar|en}/esim | Every eSIM destination. |
| https://tryapproach.net/{ar|en}/visa | The visa check for every country. |
| https://tryapproach.net/{ar|en}/premium | Approach Premium. |
| https://tryapproach.net/download | The right app store for the visitor's phone. |
A link without /ar or /en picks the visitor's language (Arabic by default).
Referral tag
We issue you a code and ready made order links that carry it as ?ref={yourCode}. When a customer
opens one of those links on a phone with the Approach app, the app keeps the code for 24 hours and every order
placed in that time is tagged to you, so we can report it.
Approach pages cannot be framed inside another site. Use links or buttons, not iframes.
Feeds and structured data
| Resource | What it is |
|---|---|
| https://tryapproach.net/merchant/products-en.xml | Shop products in English, Google Merchant format (RSS 2.0), Kuwait, KWD. |
| https://tryapproach.net/merchant/products-ar.xml | The same feed in Arabic. |
| https://tryapproach.net/sitemap.xml | Every public page in both languages. |
The feeds refresh every 30 minutes and list only products that are on sale to the public; each item links to
its product page. Product pages carry schema.org Product data with the same price and availability;
business pages carry LocalBusiness, category pages CollectionPage, and Premium packages
Service.
Payment links and checkout
Payment links
Our team creates a payment link for any amount with a description, in your business's name and logo. The
customer opens a secure page on pay.tryapproach.net, picks a payment method and pays; the link
expires after the time set for it and can be sent by SMS. Paid links settle to your business like any order.
Web checkout
Shops and services can be ordered and paid on tryapproach.net with no app and no login. After an
order, the customer gets a WhatsApp message with a private link to the order page: status, price breakdown and
payment. Tickets stay in the app.
Payment methods
KNET, Visa and Mastercard and Apple Pay are processed by UPayments; pay later in instalments is offered through Taly in the app. These are Approach's own payment rails: partners do not integrate with them directly, and card details never reach Approach or you.
Business tools
- Business account in the Approach app: accept or reject orders, set prices, packages, options, opening hours and closed days, publish stories and offers.
- Business dashboard: a web login (sent by e-mail when you join) with your orders, packages, calendar, transfers and a printable monthly report.
- Notifications: push on every new order and status change, a WhatsApp message for new and paid orders, and e-mail for account messages. If a customer has an urgent issue they can send one emergency message per order, which reaches you by WhatsApp.
- Visa providers: receive each visa application with its travellers and their passport and civil ID copies, download all documents as one ZIP, and move the application through its stages while the customer is kept up to date.
- Event organizers: we set up the event, seat map and prices; tickets sell in the app, can be transferred between customers, and your gate staff scan them with the Approach app. Sales reports are available during and after the event.
To join as a business, apply at tryapproach.net/en/become-an-approacher.
Security
- Keep keys and signing secrets on your servers only. Never put them in a mobile app, a web page or a public repository.
- Always call over HTTPS, and give us an https webhook URL.
- Send us your outbound IP addresses so we can lock your key to them.
- Verify every webhook signature and timestamp before you act on it.
- If a key or secret may have leaked, ask us to rotate it. The old one stops working immediately.
Support and onboarding
To go live we agree the method, test it with you, then issue your live credentials. For the Premium API that includes your plan and price; for suppliers, a test order on your sandbox.
Get API keys and support: [email protected] · +965 9000 3470