Developers

Guides

Markdown

Delivery companies

Offer your delivery service at checkout with its price, and report each shipment so the merchant and the customer can follow it.

What your app needs

You want toScopeWhere
Appear at checkout with your priceshipping.options:writePOST /delivery-options
Report the company, tracking number and stageorders.shipment:writePATCH /orders/{id}/shipment
See paid orders, items, weight and amountsorders:readGET /orders and the order.paid event
Get the recipient's name, phone and addresscustomers:readInside the order
Get the store's pickup addressstore:readGET /store
Tell the customer about a stagecustomers.notify:writePOST /orders/{id}/notifications

Offer delivery at checkout

Send your whole list. It replaces what your app sent before.

cURL
curl -X POST "https://larm.sa/stores/$STORE_ID/v1/delivery-options" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"options":[{"key":"one-hour","company_name":"Fast Courier","label":"Delivery within an hour","eta":"Within an hour","price":"25.00","cities":[]}]}'
  • The merchant decides. A new option stays off until the merchant turns it on in shipping settings. It goes back to off when you change its price or company name; other edits keep it on.
  • The price is fixed. Each option has one price from 0 to 1000 SAR, sent as a string. Larm does not call your server for a live rate.
  • Cities. An empty cities list means every city in Saudi Arabia. To limit an option, list each city in Arabic, the way customers write it in their address; an English name does not match. Options are not offered for addresses outside Saudi Arabia.
  • It can leave checkout. Your options stop showing when your app is suspended or uninstalled, or the merchant revokes the scope.

Read enabled from GET /delivery-options to see what the merchant turned on.

When a customer chooses your option

The price is added to the order's totals.shipping, and the order carries your option:

JSON
"delivery": {
  "source": "app",
  "app_id": "1f2e3d4c-5b6a-4978-8695-a4b3c2d1e0f9",
  "option_id": "one-hour",
  "label": "Delivery within an hour",
  "carrier": "Fast Courier",
  "status": "pending",
  "tracking_number": null,
  "tracking_url": null,
  "updated_at": "2026-11-02T09:30:00.000Z"
}

Listen for order.paid and start delivery only when delivery.app_id is your app. delivery shows any shipment, whoever handles it, and delivery.source says who: app, merchant or larm. It is null before any shipment.

Items carry sku, options and weight_grams, and with customers:read the order carries customer.phone and shipping_address. Collect from pickup_address in GET /store.

Report the shipment

cURL
curl -X PATCH "https://larm.sa/stores/$STORE_ID/v1/orders/200123/shipment" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"status":"out_for_delivery","tracking_number":"FC-20145","tracking_url":"https://track.example.com/FC-20145","label_url":"https://labels.example.com/FC-20145.pdf"}'
statusWhat happens
shippedThe customer sees it on the way. The first movement sends the shipping notice once
out_for_deliveryThe customer sees it out for delivery
delivery_attemptedThe customer sees that the attempt failed
deliveredThe order is completed and the customer is told it arrived. No update is accepted after this
returnedThe customer sees it returned. Any refund is the merchant's decision

carrier, tracking_number, tracking_url and label_url keep their last value when you omit them. carrier is required only when the order has no delivery option of yours. Both links must be https. The merchant prints the label from the order. Only your own reply carries label_url: other apps and the customer never see it.

Other apps with orders:read receive every change as order.shipment.updated.

Tell the customer

Your first shipped or out_for_delivery sends the shipping notice by email and text message, once. For the later stages, send a text message yourself:

cURL
curl -X POST "https://larm.sa/stores/$STORE_ID/v1/orders/200123/notifications" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"channel":"sms","template":"out_for_delivery"}'

The templates are order_shipped, out_for_delivery and delivered. Each goes once per order, the merchant pays for it from their message package and can turn it off, and the wording is fixed. To say more, send an email with your own text. See Notify the order customer.

Who owns a shipment

The first to report owns it. You receive SHIPMENT_OWNED_ELSEWHERE when the merchant recorded the shipment or corrected yours, or when another app reported it. The merchant can always correct a shipment, and yours stops updating from then on.

Money

The customer pays your price with the order, and it stays with the merchant in their settlement. Larm charges nothing on these orders and does not book them with its own carriers. Bill the merchant under your own agreement.

    ↑↓ moveEnter openEsc close