Connect your ERP
Run deliveries in the N-Ways console and keep your ERP in step: every event reaches your system as it happens, signed and retried, and can be pulled again at any time.
On this page
For companies that run their deliveries in the N-Ways console and want the same data in their own ERP. Choose Run deliveries here, synced to our ERP when you sign up, and the console puts webhooks, the delivery log and this guide first. Send this page to whoever connects your ERP: your IT team or your integration partner.
How the data flows
- Your dispatchers work in the console (or the N-Ways Business app): deliveries, riders, N-Ways drivers, alerts.
- Every change is an event. N-Ways sends it to your HTTPS endpoint within seconds, signed with your endpoint’s secret.
- Your ERP updates its record, found by the reference you gave the delivery or by N-Ways’ id.
- Nothing is lost. Failed calls are retried for about 22 hours; you can retry any of them from the delivery log, and pull every event again by date with the export API.
1. Add your endpoint
In the console: Settings → Webhooks → Add webhook. Give an HTTPS address reachable from the internet and choose every event or only those your ERP needs. The signing secret (whsec_…) is shown once: store it with your other secrets. Up to 10 endpoints per organisation, each with its own custom headers (an API key for your gateway, for example).
Or with a server key:
curl -X POST "https://nways.ng/maps/v1/fleet/webhooks" \
-H "X-NWays-Api-Key: YOUR_SERVER_KEY" -H "Content-Type: application/json" \
-d '{"url": "https://erp.example.com/nways/events"}'2. Send a test event
Send test on the webhook posts a ping event. The console’s Logs → Webhook deliveries shows each attempt, your server’s answer and when the next try is due. Answer with any 2xx within 10 seconds; do slow work (posting to the ERP) after answering.
3. Check the signature
Every call carries X-NWays-Signature: t=<unix seconds>,v1=<hex>, where v1 is HMAC-SHA256 of "<t>.<raw body>" with your endpoint’s secret. Check it on the raw body, before parsing, and refuse a timestamp more than 5 minutes off.
using System.Security.Cryptography;
using System.Text;
static bool Verified(string raw, string header, string secret)
{
var parts = header.Split(',').Select(p => p.Split('=', 2)).ToDictionary(p => p[0], p => p.Length > 1 ? p[1] : "");
if (!long.TryParse(parts.GetValueOrDefault("t"), out var t)) return false;
if (Math.Abs(DateTimeOffset.UtcNow.ToUnixTimeSeconds() - t) > 300) return false;
using var mac = new HMACSHA256(Encoding.UTF8.GetBytes(secret));
var want = Convert.ToHexString(mac.ComputeHash(Encoding.UTF8.GetBytes($"{t}.{raw}"))).ToLowerInvariant();
return CryptographicOperations.FixedTimeEquals(Encoding.UTF8.GetBytes(want), Encoding.UTF8.GetBytes(parts.GetValueOrDefault("v1", "")));
}import com.sap.gateway.ip.core.customdev.util.Message
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
def Message processData(Message message) {
def raw = message.getBody(String)
def parts = message.getHeaders()['X-NWays-Signature'].split(',').collectEntries { it.split('=', 2) as List }
long t = parts.t as long
if (Math.abs(System.currentTimeMillis() / 1000 - t) > 300) throw new Exception('old signature')
def mac = Mac.getInstance('HmacSHA256')
mac.init(new SecretKeySpec(message.getProperty('NWAYS_SECRET').bytes, 'HmacSHA256'))
def want = mac.doFinal("${t}.${raw}".bytes).encodeHex().toString()
if (!java.security.MessageDigest.isEqual(want.bytes, (parts.v1 ?: '').bytes)) throw new Exception('bad signature')
return message
}import hashlib, hmac, time
def verified(raw: bytes, header: str, secret: str) -> bool:
parts = dict(p.split("=", 1) for p in header.split(",") if "=" in p)
if abs(time.time() - int(parts.get("t", 0))) > 300:
return False
want = hmac.new(secret.encode(), parts["t"].encode() + b"." + raw, hashlib.sha256).hexdigest()
return hmac.compare_digest(want, parts.get("v1", ""))4. Map the fields
Where each field of a delivery event (data.task) usually goes. Keep N-Ways’ id as an external reference on your record, so every later event finds it; put your own document number in the delivery’s reference when you create it, and it comes back in every event.
| Meaning | N-Ways | SAP S/4HANA | Odoo | Dynamics 365 |
|---|---|---|---|---|
| Your own reference | reference | Outbound delivery (LIKP-VBELN) | stock.picking origin | Shipment ID |
| Delivery number | id, ref | External ID (LIKP-LIFEX) | A custom field, e.g. x_nways_id | External reference |
| Status | status | POD status (LIKP-PDSTK) | state | Shipment status |
| Customer | recipientName, recipientPhone | Ship-to party (KUNNR) | partner_id | Delivery name and contact |
| Drop-off | dropoff.address, dropoff.lat/lng | Ship-to address (ADRC) | Partner address | Delivery address |
| Rider | vehicleId | Shipment (VTTK), means of transport | carrier_id or a driver field | Carrier, vehicle |
| Times | pickedUpAt, endedAt | Actual goods issue (WADAT_IST) | date_done | Actual ship and delivery dates |
| Proof of delivery | proofs[] | POD (VLPOD) attachment | Attachment on the transfer | Document attachment |
Statuses: created → assigned → picked_up → arriving → completed, or failed (with failureReason) or cancelled. Events can arrive twice or out of order: keep the event ids you’ve handled and trust the task’s status over the order of arrival. There are no money fields, by design.
5. Reconcile
If your ERP was down, nothing is lost. Retry any delivery from Logs → Webhook deliveries, or pull the events again by date (JSON or CSV, the same payloads the webhooks send):
curl "https://nways.ng/maps/v1/fleet/events/export?format=json&from=2026-10-01&to=2026-10-16" \
-H "X-NWays-Api-Key: YOUR_SERVER_KEY"Deliveries, vehicles and drivers can also be read at any time from the fleet API (GET /maps/v1/fleet/tasks, /vehicles, /drivers), for a nightly check that both sides agree. Use a key restricted to your servers’ IP addresses and to the fleet API.
Which events
Every event in the webhooks list: deliveries (task.*, delivery.rated), drivers and vehicles (connection.*, driver.availability_changed, vehicle.offline), requests to N-Ways drivers (dispatch.*), zones and alerts (zone.*, asset.*). Payloads carry version 2026-10-16; fields are only ever added within a version.