Connect WhatsApp and marketing tools

Send every AlliDesk event — points earned, COD confirmation, a return approved, a warranty claim — to Spur, BIK, Interakt, WATI, AiSensy, Zapier or any tool with a webhook URL. Your tool sends the WhatsApp message from its own approved templates.

  1. How it works

    AlliDesk does not hold a WhatsApp account of its own. Your WhatsApp tool already has your number, your approved templates and your flows. You give AlliDesk the tool's webhook URL; when an event you picked happens, AlliDesk sends it there as JSON within seconds, and the tool's flow sends the message.

    1. In your tool, add a webhook trigger to a flow, journey or workflow, and copy the URL (and token, if it shows one).
    2. In AlliDesk open Settings → Integrations → WhatsApp & marketing tools, press Connect beside your tool, paste it, tick the events and Save.
    3. Press Send test event with your own number. Your tool shows what arrived; map phone, name and the fields under data into your template.
    4. Switch the flow on in your tool. Every delivery shows under Recent deliveries in AlliDesk, with the tool's answer.

    You can connect up to ten tools, and one tool more than once — for example one Spur flow for loyalty and another for returns. Only a store owner can connect, change or remove a tool.

  2. Spur

    Start a Spur WhatsApp flow from any AlliDesk event.

    1. In Spur open Automations → Automation Flows → Create New Flow.
    2. Pick WhatsApp as the channel and Webhook as the trigger. Spur shows the flow's webhook URL — copy it.
    3. In AlliDesk open Settings → Integrations → WhatsApp & marketing tools, press Connect beside Spur, and paste it, tick the events you want, and Save.
    4. Press Send test event — the tool now has a sample to map.
    5. Back in Spur press Test Webhook → Check for Received Requests. Map phone and name, then use fields such as {{trigger.data.points}} in your template.
    URLFrom the flow's Webhook trigger in Spur.
    TokenSpur's webhook URL needs no token.
    BodyAlliDesk's standard JSON (below).
    PhoneSpur needs a phone number, so an event about someone with no phone is not sent to it (it shows as Skipped).

    Spur's own guide

  3. BIK

    Trigger a BIK journey on WhatsApp from any AlliDesk event.

    1. In BIK open the Journey Builder and start a journey on the WhatsApp channel with Webhook as the trigger.
    2. Copy the webhook URL BIK generates for that journey.
    3. In AlliDesk open Settings → Integrations → WhatsApp & marketing tools, press Connect beside BIK, and paste it, tick the events you want, and Save.
    4. Press Send test event — the tool now has a sample to map.
    5. In BIK map phone number and email as the unique IDs, then pick the other fields from the variable picker.
    URLFrom the journey's Webhook trigger in BIK.
    TokenOnly if BIK shows you one.
    BodyAlliDesk's standard JSON (below).
    PhoneBIK needs a phone number, so an event about someone with no phone is not sent to it (it shows as Skipped).

    BIK's own guide

  4. Interakt

    Every event lands on the customer's Interakt profile, ready for campaigns.

    1. In Interakt open Settings → Developer Setting and copy the Secret Key.
    2. In AlliDesk open Settings → Integrations → WhatsApp & marketing tools, press Connect beside Interakt, and paste it as it is — Interakt already encodes it — tick the events, and Save.
    3. Press Send test event, then open that customer in Interakt: the event (for example “Points earned”) shows with its details as traits.
    4. Use those events when you build campaigns in Interakt.
    URLhttps://api.interakt.ai/v1/public/track/events/
    TokenInterakt → Settings → Developer Setting → Secret Key. Sent as Authorization: Basic <key>.
    BodyInterakt's Track Events format (below).
    PhoneInterakt needs a phone number, so an event about someone with no phone is not sent to it (it shows as Skipped).

    Interakt's own guide

  5. WATI through Pabbly Connect

    Send a WATI template for any event, through a Pabbly Connect workflow.

    1. In Pabbly Connect create a workflow with Webhook by Pabbly as the trigger and copy its webhook URL.
    2. In AlliDesk open Settings → Integrations → WhatsApp & marketing tools, press Connect beside WATI, and paste it, tick the events you want, and Save.
    3. Press Send test event so Pabbly captures a sample.
    4. Add the WATI action that sends a template message, and map phone and the event's fields into the template.
    URLFrom the Webhook by Pabbly trigger.
    TokenPabbly's webhook URL needs no token.
    BodyAlliDesk's standard JSON (below).
    PhoneWATI needs a phone number, so an event about someone with no phone is not sent to it (it shows as Skipped).

    WATI's own guide

  6. AiSensy through Pabbly Connect

    Send an AiSensy template for any event, through a Pabbly Connect workflow.

    1. In Pabbly Connect create a workflow with Webhook by Pabbly as the trigger and copy its webhook URL.
    2. In AlliDesk open Settings → Integrations → WhatsApp & marketing tools, press Connect beside AiSensy, and paste it, tick the events you want, and Save.
    3. Press Send test event so Pabbly captures a sample.
    4. Add the WhatsApp by AiSensy action that sends a template message, and map phone and the event's fields.
    URLFrom the Webhook by Pabbly trigger.
    TokenPabbly's webhook URL needs no token.
    BodyAlliDesk's standard JSON (below).
    PhoneAiSensy needs a phone number, so an event about someone with no phone is not sent to it (it shows as Skipped).

    AiSensy's own guide

  7. Pabbly Connect

    Catch events in Pabbly and pass them to any app it connects.

    1. In Pabbly Connect create a workflow with Webhook by Pabbly as the trigger and copy its webhook URL.
    2. In AlliDesk open Settings → Integrations → WhatsApp & marketing tools, press Connect beside Pabbly Connect, and paste it, tick the events you want, and Save.
    3. Press Send test event so Pabbly captures a sample, then add the actions you want.
    URLFrom the Webhook by Pabbly trigger.
    TokenPabbly's webhook URL needs no token.
    BodyAlliDesk's standard JSON (below).

    Pabbly Connect's own guide

  8. Zapier

    Start a Zap from any event and reach WATI, Zoko or thousands of apps.

    1. In Zapier create a Zap with Webhooks by Zapier → Catch Hook as the trigger and copy the webhook URL. Webhooks by Zapier needs a paid Zapier plan.
    2. In AlliDesk open Settings → Integrations → WhatsApp & marketing tools, press Connect beside Zapier, and paste it, tick the events you want, and Save.
    3. Press Send test event, then in Zapier test the trigger to pull in the sample and add your action.
    URLFrom Webhooks by Zapier → Catch Hook.
    TokenZapier's catch hook needs no token.
    BodyAlliDesk's standard JSON (below).

    Zapier's own guide

  9. Make

    Run a Make scenario from any event.

    1. In Make start a scenario with Webhooks → Custom webhook, add a webhook and copy its address.
    2. In AlliDesk open Settings → Integrations → WhatsApp & marketing tools, press Connect beside Make, and paste it, tick the events you want, and Save.
    3. Press Send test event while Make is listening, so it learns the data structure.
    URLFrom Webhooks → Custom webhook.
    TokenMake's custom webhook address needs no token.
    BodyAlliDesk's standard JSON (below).

    Make's own guide

  10. n8n

    Start an n8n workflow from any event.

    1. In n8n add a Webhook node, set the method to POST, and copy the Production URL.
    2. If you set Header Auth on the node, put the same header name and value in Token below.
    3. In AlliDesk open Settings → Integrations → WhatsApp & marketing tools, press Connect beside n8n, and paste it, tick the events you want, and Save.
    4. Activate the workflow, then press Send test event.
    URLThe Webhook node's Production URL.
    TokenOnly with Header Auth on the node.
    BodyAlliDesk's standard JSON (below).

    n8n's own guide

  11. Custom webhook

    Any other WhatsApp tool, CRM or server that gives you a webhook URL.

    1. In your tool, create an incoming webhook (it may be called a webhook trigger or API trigger) and copy its URL and token.
    2. In AlliDesk open Settings → Integrations → WhatsApp & marketing tools, press Connect beside Custom webhook, and paste the URL, and the token with the header your tool expects. Most use Authorization: Bearer.
    3. Tick the events, Save, and press Send test event to see exactly what arrives.
    4. Map phone, name and the fields under data into your message. Every request is signed, so your server can check it came from AlliDesk.
    URLMust start with https://.
    TokenLeave blank if your tool needs none.
    BodyAlliDesk's standard JSON (below).
  12. What AlliDesk sends

    One POST per event, per person, per connection, with Content-Type: application/json. Only HTTPS URLs on the public internet are accepted.

    X-AlliDesk-EventThe event key, e.g. loyalty.points_earned.
    X-AlliDesk-DeliveryA unique id for this delivery; the same on every retry, so you can ignore a repeat.
    X-AlliDesk-TimestampUnix seconds when it was sent.
    X-AlliDesk-Signaturesha256=HMAC of timestamp, a dot and the body, with the connection's signing secret.
    AuthorizationYour token, when you saved one: Bearer, Basic, or exactly as typed, under the header name you chose.
    Standard body
    {
      "event": "loyalty.points_earned",
      "event_name": "Points earned",
      "event_id": "cmh3w2k0p0004",
      "occurred_at": "2026-09-17T10:42:07.000Z",
      "test": false,
      "audience": "customer",
      "phone": "919876543210",
      "phone_national": "9876543210",
      "country_code": "91",
      "name": "Asha Verma",
      "first_name": "Asha",
      "email": "asha@example.com",
      "store": {
        "name": "Your store",
        "domain": "yourstore.in",
        "currency": "INR"
      },
      "data": {
        "first_name": "Asha",
        "points": "120",
        "points_name": "points",
        "reason": "a product review",
        "balance": "820",
        "account_url": "https://yourstore.in/apps/account"
      }
    }
    Interakt body
    {
      "phoneNumber": "9876543210",
      "countryCode": "+91",
      "event": "Points earned",
      "traits": {
        "first_name": "Asha",
        "points": "120",
        "points_name": "points",
        "reason": "a product review",
        "balance": "820",
        "account_url": "https://yourstore.in/apps/account",
        "allidesk_event": "loyalty.points_earned",
        "allidesk_event_id": "cmh3w2k0p0004",
        "store_name": "Your store",
        "email": "asha@example.com"
      }
    }
    phoneCountry code and number, digits only (919876543210) — the shape Spur and most tools take. Also split into phone_national and country_code. Null when AlliDesk has no number.
    name, first_name, emailThe customer, or for a team alert your store's name and the alert's email.
    audiencecustomer, or store_team for alerts meant for you.
    dataThe event's own fields, as text or numbers — listed for every event below.
    testtrue for a test event sent from the settings page. Filter these out of a live flow if you need to.
  13. Every event (44)

    Tick any of these on a connection. A new event AlliDesk adds appears here and on the settings page.

    Sign-in

    login.otpabout a customerSign-in code. The one-time code a customer asked for to sign in to their account.
    data: codestore_nameminutes

    Orders and accounts

    orders.cod_confirm_requestedabout a customerConfirm your cash-on-delivery order. Asks the customer to confirm a COD order before it is processed.
    data: first_nameorder_nameorder_totalconfirm_url
    accounts.inviteabout a customerAccount invitation. Invites a customer to create (or sign in to) their account. Used by campaigns and the Invite button.
    data: first_namestore_nameaccount_urllogin_url

    Returns and exchanges

    requests.receivedabout a customerRequest received. Confirms to the customer that their return, exchange or replacement request is in.
    data: first_nameorder_namerequest_typerequest_statusstore_nameaccount_url
    requests.status_changedabout a customerRequest status update. Sent to the customer whenever their request moves: approved, pickup booked, received, settled, rejected.
    data: first_nameorder_namerequest_typerequest_statusnotestore_nameaccount_url

    Loyalty

    loyalty.points_earnedabout a customerPoints earned. Tells the customer when an action such as a review, birthday or sign-up added points.
    data: first_namepointspoints_namereasonbalanceaccount_url
    loyalty.tier_upabout a customerMoved up a tier. Congratulates the customer when they reach a new tier.
    data: first_nametier_nametier_benefitspoints_namestore_nameaccount_url

    Referrals

    referrals.rewardedabout a customerReferral reward. Tells the referrer their friend's order went through and their reward is in.
    data: first_namefriend_namerewardstore_nameaccount_url

    GST invoices

    gst.invoiceabout a customerGST invoice. The tax invoice for an order, with the PDF attached.
    data: first_namestore_nameorder_nameinvoice_numberinvoice_dateamountinvoice_url
    gst.estimateabout a customerGST estimate. A quotation for the customer, with the PDF attached and a link to accept it from their account.
    data: first_namestore_nameinvoice_numberinvoice_dateamountvalid_untilinvoice_urlaccount_url
    gst.credit_noteabout a customerGST credit note. The credit note issued when an order is refunded, with the PDF attached.
    data: first_namestore_nameorder_nameinvoice_numberinvoice_dateamountinvoice_url
    gst.statementabout a customerGST statement. A period's purchases as one statement, with the consolidated tax summary attached. Sent when someone asks for it, never on its own.
    data: first_namestore_nameperiodinvoice_countitem_countamounttax_amountbalance_duestatement_dateaccount_url

    Reviews

    reviews.requestabout a customerReview request. Asks the customer to review what they bought, a few days after the order lands.
    data: first_namestore_nameproductorder_namereview_url
    reviews.couponabout a customerThank-you coupon. Sends the discount code a customer earned for writing a review.
    data: first_namestore_namecoderewarddays

    Store alerts

    reviews.alertto your teamlow-rated review. Tells your team when a review comes in at or below the rating you set.
    data: store_nameratingproductbodystatus
    alerts.low_stockto your teamlow stock. A variant fell to or below the threshold.
    data: productvariantavailablestore_name
    alerts.new_requestto your teamnew request. A customer raised a return, exchange or replacement.
    data: customer_nameorder_namerequest_typeamountdashboard_urlstore_name
    alerts.cod_unconfirmedto your teamCOD order still unconfirmed. A cash-on-delivery order has waited longer than the threshold without confirmation.
    data: order_namehoursstore_name
    warranty.merchant_new_claimto your teamNew claim filed. Alert to the merchant when a claim comes in.
    data: customer_nameclaim_numberproduct_titleissue_typedescriptiondashboard_url
    warranty.merchant_new_registrationto your teamNew marketplace registration. Alert when a customer registers a marketplace purchase for review.
    data: customer_nameproduct_titlemarketplacepurchase_datedashboard_url

    Wishlist

    wishlist.price_dropabout a customerPrice drop on a saved item. A product on the customer's wishlist got cheaper.
    data: first_nameitemsstore_namewishlist_url
    wishlist.back_in_stockabout a customerSaved item back in stock. A product on the customer's wishlist is available again.
    data: first_nameitemsstore_namewishlist_url

    Warranty

    warranty.activated_purchaseabout a customerWarranty activated on purchase. Sent when a store purchase is registered on its own.
    data: first_namestore_nameproduct_titleplan_nameexpires_ondays_leftaccount_url
    warranty.activated_manualabout a customerWarranty activated — manual registration. Sent when a customer's own registration (marketplace or shop purchase) is approved or activates.
    data: first_namestore_nameproduct_titleplan_nameexpires_ondays_leftaccount_url
    warranty.registration_rejectedabout a customerMarketplace registration rejected. Sent when a registration cannot be verified.
    data: first_namestore_nameproduct_titleplan_nameexpires_ondays_leftaccount_urlreason
    warranty.extended_purchasedabout a customerExtended warranty purchased. Sent when a customer buys an extended plan.
    data: first_namestore_nameproduct_titleplan_nameexpires_ondays_leftaccount_url
    warranty.expiring_7about a customerWarranty expiring in 7 days. Urgent reminder a week before expiry.
    data: first_namestore_nameproduct_titleplan_nameexpires_ondays_leftaccount_urlextend_line
    warranty.claim_receivedabout a customerClaim received. Immediate confirmation after a claim is filed.
    data: first_namestore_nameproduct_titleplan_nameexpires_ondays_leftaccount_urlclaim_numberclaim_statusclaim_urlresolutionsla_hours
    warranty.claim_approvedabout a customerClaim approved. Sent when the claim is approved, with the resolution.
    data: first_namestore_nameproduct_titleplan_nameexpires_ondays_leftaccount_urlclaim_numberclaim_statusclaim_urlresolutionnext_step
    warranty.claim_deniedabout a customerClaim not approved. Sent when the claim is rejected, with the reason.
    data: first_namestore_nameproduct_titleplan_nameexpires_ondays_leftaccount_urlclaim_numberclaim_statusclaim_urlresolutionreason
    warranty.claim_info_neededabout a customerMore information needed. Sent when the team asks the customer for photos, a video or details.
    data: first_namestore_nameproduct_titleplan_nameexpires_ondays_leftaccount_urlclaim_numberclaim_statusclaim_urlresolutionrequest
    warranty.claim_completedabout a customerClaim completed and closed. Final note when a claim is resolved and closed.
    data: first_namestore_nameproduct_titleplan_nameexpires_ondays_leftaccount_urlclaim_numberclaim_statusclaim_urlresolution
    warranty.service_center_assignedabout a customerService centre assigned. Sent with the centre's address once a repair is routed there.
    data: first_namestore_nameproduct_titleplan_nameexpires_ondays_leftaccount_urlclaim_numberclaim_statusclaim_urlresolutioncenter_namecenter_addresscenter_phonecenter_hours
    warranty.item_readyabout a customerItem ready for pickup. Sent when the repair is done and the item can be collected.
    data: first_namestore_nameproduct_titleplan_nameexpires_ondays_leftaccount_urlclaim_numberclaim_statusclaim_urlresolutioncenter_namecenter_hours
    warranty.home_visit_scheduledabout a customerHome visit scheduled. Sent when a technician visit is booked.
    data: first_namestore_nameproduct_titleplan_nameexpires_ondays_leftaccount_urlclaim_numberclaim_statusclaim_urlresolutionvisit_datevisit_windowtechnician
    warranty.replacement_with_returnabout a customerReplacement (return required). Sent when a replacement ships and the old unit must be returned.
    data: first_namestore_nameproduct_titleplan_nameexpires_ondays_leftaccount_urlclaim_numberclaim_statusclaim_urlresolutionreplacement_orderreturn_instructions
    warranty.refund_issuedabout a customerRefund or store credit issued. Sent when the claim is settled in money.
    data: first_namestore_nameproduct_titleplan_nameexpires_ondays_leftaccount_urlclaim_numberclaim_statusclaim_urlresolutionamountsettlement_note

    Membership

    membership.joinedabout a customerWelcome to the programme. Sent when a membership starts, whether it was bought or granted.
    data: first_namestore_nameprogram_nameplan_namebenefitsexpires_ondays_leftsaved_totalrenew_urlaccount_url
    membership.expiringabout a customerMembership running out. Sent on the reminder days set under Membership → Settings.
    data: first_namestore_nameprogram_nameplan_namebenefitsexpires_ondays_leftsaved_totalrenew_urlaccount_url
    membership.expiredabout a customerMembership ended. Sent the day a membership lapses.
    data: first_namestore_nameprogram_nameplan_namebenefitsexpires_ondays_leftsaved_totalrenew_urlaccount_url

    Subscriptions

    subscriptions.startedabout a customerSubscription started. Sent once the customer has authorised the mandate and the first order is on its way.
    data: first_namestore_nameprogram_nameplan_namescheduleamountnext_charge_onreasonmanage_url
    subscriptions.reminderabout a customerA charge is coming. Sent the set number of days before each charge. Off by default: most shoppers would rather not hear from you every cycle.
    data: first_namestore_nameprogram_nameplan_namescheduleamountnext_charge_onreasonmanage_url
    subscriptions.payment_failedabout a customerPayment did not go through. Sent when a cycle's charge fails. The app tries again over the next few days.
    data: first_namestore_nameprogram_nameplan_namescheduleamountnext_charge_onreasonmanage_url
    subscriptions.cancelledabout a customerSubscription ended. Sent when a subscription stops, whether the customer stopped it or the shop did.
    data: first_namestore_nameprogram_nameplan_namescheduleamountnext_charge_onreasonmanage_url
  14. Who an event is about

    • A customer event carries that customer's phone, name and email, from their account on your store.
    • A store alert (low stock, a new return, a low-rated review, a COD order unconfirmed) goes once for each phone number in Alerts → Recipients, or else once for each of your Team WhatsApp numbers on the settings page.
    • A customer who answered no to “Send order updates by SMS or WhatsApp” on their account gets nothing through your tools; the delivery shows as Skipped. A sign-in code they asked for is the exception.
    • Spur, BIK, Interakt, WATI and AiSensy need a phone, so an event with no number is skipped for them.
    • The Sign-in code event carries the code itself: tick it only on a tool that sends it straight to the customer.
  15. Checking the signature

    Tools like Spur and Zapier do not need this. If the URL is your own server, check each request came from AlliDesk: copy the signing secret from the connection's Advanced section, then compare signatures on the raw body.

    import { createHmac, timingSafeEqual } from "node:crypto";
    
    // Express: app.post("/allidesk", express.raw({ type: "application/json" }), handler)
    export function fromAllidesk(rawBody, headers, signingSecret) {
      const timestamp = headers["x-allidesk-timestamp"];
      const received = String(headers["x-allidesk-signature"] ?? "").replace(/^sha256=/, "");
      // Refuse anything older than five minutes, so a copied request cannot be replayed.
      if (!timestamp || Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
      const expected = createHmac("sha256", signingSecret).update(`${timestamp}.${rawBody}`).digest("hex");
      return received.length === expected.length && timingSafeEqual(Buffer.from(received), Buffer.from(expected));
    }
  16. Retries and the log

    • Any 2xx answer is delivered. Answer quickly — AlliDesk waits 10 seconds by default (3 to 30 in Advanced).
    • A 5xx, 408, 429, a timeout or a connection error is tried again up to 5 times in all, after about ½, 1, 2, 4 minutes.
    • Other 4xx answers are not retried: they mean the URL or token is wrong. A redirect is not followed — paste the final URL.
    • Recent deliveries on the settings page shows each one with the tool's answer, for 30 days. The body is not stored, since it can carry a sign-in code.
    • Switching a connection off stops events at once, including retries still waiting.
  17. When nothing arrives

    Nothing in Recent deliveriesThe event is not ticked on the connection, the connection is off, or the event has not happened yet. Send a test event to check the connection.
    SkippedNo phone number for that person and the tool needs one, or the customer said no to WhatsApp updates.
    HTTP 401 or 403The token is wrong or missing. For Interakt, paste the Secret Key exactly as Interakt shows it.
    HTTP 404The tool's webhook URL changed, for example after the flow was recreated. Paste the new one.
    Delivered, but no WhatsAppThe request reached your tool; check the flow is switched on, the template is approved and phone is mapped to the recipient.

    Still stuck? Write to hello@allidesk.com with the connection's name and the time of the delivery.

Didn't find it?

Write to hello@allidesk.com. A person replies, usually within one business day.