Events
The append-only supply chain event log, one event or up to 1,000 at a time.
Endpoints
Record an event
https://api.dawatrack.com/partner-api/v1/events/
Add one event to the append-only supply chain log: commission, ship, receive, dispense, quarantine and more.
events:write
Limit 5,000 per day
You can only report events for a GTIN and batch you have a relationship with, as the ledger records it: you are the product's registered manufacturer or a contract packer it authorized for the GTIN; or an event for that batch was reported by you, by your linked supplier account (including a shipment a pharmacy recorded receiving from it), or by a facility you're linked to. Otherwise 403. The same rule decides which batches, units and event histories you can read. One exception: a RECEIVE of stock you received from a party outside DawaTrack, naming it as sender, may be of any product, as a pharmacy's delivery note from an outside supplier is: every trading partner records its own receipts. It needs an approved account and production credentials, and then the batch is yours to report on like any other. The same goes for your opening stock: a RECEIVE with opening_balance: true, once per batch, before any other event of yours on it, within 30 days of your first.
parent_event must be an event you can see for the same GTIN and batch, and corrects_event one of your own. occurred_at defaults to now.
A document you cancelled in your own system is a RETRACT: send event_type RETRACT and the event's id as corrects_event, nothing else. The event did not occur (GS1 EPCIS error declaration, reason did_not_occur): every reader leaves it out, the EPCIS export carries it with its errorDeclaration, and a consignment whose lines are all retracted is cancelled. Once per event, and not once something follows from it (a receipt of the shipment, a shipment from the receipt): retract that first. A wrong detail is a correction instead: a new event of the same type naming the old one as corrects_event.
A stock event names the event it follows from as parent_event, so the graph can walk to and from it; otherwise 400 with detail, field (parent_event) and event_type. A RECEIVE names the SHIP it received, or, for stock from outside DawaTrack, its sender (name, and its ppb_licence or gln; a sender on DawaTrack is 400: name its SHIP). A DISPENSE names its RECEIVE, a RELEASE its QUARANTINE, a DISAGGREGATE its AGGREGATE. A SHIP, QUARANTINE or TRANSFER names the RECEIVE its units came from once you have received the lot on DawaTrack; before that the stock is your own and it needs none.
RECEIVE_LINK, SHIP_ANSWER (a supplier's answer to a delivery a pharmacy reported), RECALL_ACKNOWLEDGMENT (a party outside DawaTrack's answer to a recall notice) and RECEIPT_ANSWER (a receiver outside DawaTrack's report of a short, damaged or refused line) are written by DawaTrack, not by partners: each is 400.
The parent must be a type that can precede the event: a RECEIVE follows a SHIP or TRANSFER; a SHIP a RECEIVE, COMMISSION, AGGREGATE or DISAGGREGATE; a DISPENSE, QUARANTINE or TRANSFER a RECEIVE, COMMISSION or DISAGGREGATE; a RELEASE a QUARANTINE. A COMMISSION names none. Otherwise 400. A parent_event you can't reference is 400, the same answer as an id that doesn't exist.
On a SHIP, destination_schema_name (optional) names the DawaTrack facility receiving the shipment. When that facility receives the same GTIN and batch, its receipt is linked to your event, so traces and EPCIS show the hop from you to them. A name that isn't a DawaTrack facility is 400; on any other event type it's 400 too.
If your account is linked to a supplier, a SHIP can instead name another supplier with destination_supplier_ppb_license_number: the PPB licence number of an approved supplier on DawaTrack. That supplier is emailed and confirms receipt on its portal. An unknown or unapproved licence, your own, naming a facility as well, or a sandbox credential is 400.
Every SHIP is a line of a consignment (a despatch advice). Send consignment with your own number (1 to 40 letters, digits, ., _, / or -) and, optionally, reference, carrier_name, waybill_number, vehicle_registration, driver_name, driver_phone and expected_delivery_date: SHIP events with the same number are lines of one consignment, to one receiver, and a number you already used for another receiver is 400 (CONSIGNMENT_RECEIVER_MISMATCH in a bulk job). Leave it out and DawaTrack numbers a one-line consignment. The number goes on the ledger and in EPCIS as a desadv business transaction; the carrier, waybill, vehicle and driver are kept off the ledger. The response's consignment_number names it. consignment on any other event type is 400.
A SHIP that names an sscc: the carton's GS1 Digital Link URI, https://dawatrack.com/00/<SSCC> (the QR on a GS1 carton label), opens its receiver's page to confirm the consignment. Holding the carton shows only who sent it; confirming needs the code emailed to the receiver's address on file.
A sender (on a RECEIVE) or recipient (on a SHIP) outside DawaTrack needs an email and a phone, both: the email is how a recall reaches it now, the phone how an SMS will. The phone is given with its country code (+254…; a Kenyan 07… or 01… number works too) and kept in E.164. Otherwise 400. The recipient is emailed at once that the consignment is on its way, with one link to confirm what it received (it records the receipt on /capture/{token}/ or with POST /capture/receive/).
A gtin with a wrong GS1 check digit is 400, and the message says what the digit should be.
On a SHIP or COMMISSION, batch_number must be a GS1 batch (AI 10): at most 20 characters from GS1 character set 82, after spaces are removed, so it can be printed in a DataMatrix; otherwise 400. Other events aren't refused.
expiry_date and manufacture_date (optional, YYYY-MM-DD) are the lot's details. The first event for a GTIN and batch with an expiry records them for the lot, owned by the product's manufacturer when it is registered on DawaTrack. After that every event for the lot carries the same dates: one you send that differs is 400 naming the owner, and one you leave out takes the lot's. A manufacture date in the future, or on or after the expiry, is 400. An expiry_date inside raw_payload is still read for a lot not yet known, and never refused.
A SHIP or COMMISSION of a product saved as a draft on the supplier portal is 403 until its manufacturer activates it.
A SHIP by the product's own manufacturer is 403 while PPB's published register shows its registration expired, or DawaTrack staff confirmed it doesn't match its registration. Staff can allow shipping for a set time while a renewal is filed. Other partners' events for the product are not refused. GET /products/{gtin}/ shows the owner the reason under ppb_register.hold.
Request body
JSON. Send Content-Type: application/json.
-
event_typeenum RequiredThe kind of event.
Possible values:COMMISSIONSHIPRECEIVETRANSFERDISPENSEQUARANTINERELEASEAGGREGATEDISAGGREGATERECEIVE_LINKSHIP_ANSWERRECALL_ACKNOWLEDGMENTRECEIPT_ANSWERRETRACT -
gtinstring OptionalThe product's GS1 GTIN, as 14 digits.
-
batch_numberstring OptionalThe batch or lot number.
-
serial_numberstring OptionalThe unit's serial number.
-
ssccstring OptionalAn 18-digit GS1 Serial Shipping Container Code.
-
quantityinteger OptionalQuantity of units/items involved in this event (for batch-level or aggregated events).
-
expiry_datedate or null OptionalThe lot's expiry date (GS1 AI 17). Optional. When the lot (GTIN and batch) is already on DawaTrack it must match the lot's, and a blank one takes the lot's; the first declaration with an expiry creates the lot. A raw_payload.expiry_date is still read for a lot not yet known.
-
manufacture_datedate or null OptionalThe lot's manufacture date (GS1 AI 11). Optional, checked against the lot like expiry_date; not in the future, and before the expiry.
-
parent_eventinteger or null OptionalParent event forming the distribution graph (e.g. COMMISSION/RECEIVE -> SHIP/DISPENSE).
-
corrects_eventinteger or null OptionalEvent being corrected by this immutable record.
-
actor_idstring OptionalWho or what produced the event.
-
facility_idstring OptionalThe facility where the event happened.
-
idempotency_keystring OptionalOptional key making this single event idempotent for your credential.
-
occurred_atdatetime OptionalDefaults to now if omitted.
-
raw_payloadobject OptionalFor AGGREGATE events, the packed children as a list of {gtin, serial}.
-
destination_schema_namestring OptionalSHIP only, optional: the DawaTrack facility (its schema_name) receiving this shipment. When that facility receives the same GTIN and batch, its receipt is linked to this event.
-
destination_supplier_ppb_license_numberstring OptionalSHIP only, optional, for a partner linked to a supplier account: the PPB licence number of the approved DawaTrack supplier receiving this shipment. It confirms receipt on its Receiving screen. Use this or destination_schema_name, not both.
-
senderobject OptionalRECEIVE only, optional: the sender of stock that came from outside DawaTrack, so there is no SHIP to name as parent_event. The receipt is where the graph picks the lot up. Not with parent_event; not for a sender on DawaTrack, whose SHIP you name instead.
-
namestring Required -
ppb_licencestring Optional -
glnstring Optional -
emailstring OptionalHow a recall reaches this party: kept on its party record, off the ledger, and only used to send it recall notices. An email and a phone are both required; the email is what a recall notice is sent to now. The phone is stored in E.164 (+254...); a Kenyan number may be given as 07... or 01...
-
phonestring OptionalHow a recall reaches this party: kept on its party record, off the ledger, and only used to send it recall notices. An email and a phone are both required; the email is what a recall notice is sent to now. The phone is stored in E.164 (+254...); a Kenyan number may be given as 07... or 01...
-
-
opening_balanceboolean OptionalRECEIVE only, optional: true when this is stock you held when you started on DawaTrack (opening stock, as an ERP's initial stock entry), so it came from no one on record: no parent_event, no sender. Once per lot, only for a lot you have no events on yet, and within 30 days of your first opening-stock receipt. The trace reads "Opening stock, declared by <you> on <date>".
Default:
False -
recipientobject OptionalSHIP only, optional: the buyer of stock you sent outside DawaTrack, so a recall can reach it. Not with destination_schema_name or destination_supplier_ppb_license_number; not for a party on DawaTrack, which you name by those instead.
-
namestring Required -
ppb_licencestring Optional -
emailstring OptionalHow a recall reaches this party: kept on its party record, off the ledger, and only used to send it recall notices. An email and a phone are both required; the email is what a recall notice is sent to now. The phone is stored in E.164 (+254...); a Kenyan number may be given as 07... or 01...
-
phonestring OptionalHow a recall reaches this party: kept on its party record, off the ledger, and only used to send it recall notices. An email and a phone are both required; the email is what a recall notice is sent to now. The phone is stored in E.164 (+254...); a Kenyan number may be given as 07... or 01...
-
-
consignmentobject OptionalSHIP only, optional: the consignment (despatch advice) this shipment is a line of: your number, carrier, waybill, vehicle, driver and expected date. Without it, the SHIP is a one-line consignment DawaTrack numbers. The response's consignment_number names it.
-
numberstring OptionalYour own despatch advice number, unique among your consignments (1 to 40 letters, digits, '.', '_', '/' or '-'). SHIP events with the same number are lines of one consignment, to one receiver. Leave it out and DawaTrack numbers a one-line consignment.
-
referencestring OptionalYour order.
-
carrier_namestring Optional -
waybill_numberstring Optional -
vehicle_registrationstring Optional -
driver_namestring Optional -
driver_phonestring Optional -
expected_delivery_datedate or null Optional
-
Example request
curl -X POST https://api.dawatrack.com/partner-api/v1/events/ \
-H "Authorization: Bearer $DAWATRACK_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"event_type": "SHIP",
"gtin": "06164004321562",
"batch_number": "BTH-2026-041",
"quantity": 2600,
"expiry_date": "2028-06-30",
"manufacture_date": "2026-06-01",
"destination_schema_name": "pharmacy_a",
"consignment": {
"number": "DESADV-0001",
"carrier_name": "Lake Basin Couriers",
"waybill_number": "WB-31",
"expected_delivery_date": "2026-10-03"
},
"occurred_at": "2026-10-01T09:00:00Z"
}'
import uuid
import requests
token = "..." # from POST /oauth/token/
response = requests.post(
"https://api.dawatrack.com/partner-api/v1/events/",
headers={"Authorization": f"Bearer {token}", "Idempotency-Key": str(uuid.uuid4())},
json={
"event_type": "SHIP",
"gtin": "06164004321562",
"batch_number": "BTH-2026-041",
"quantity": 2600,
"expiry_date": "2028-06-30",
"manufacture_date": "2026-06-01",
"destination_schema_name": "pharmacy_a",
"consignment": {
"number": "DESADV-0001",
"carrier_name": "Lake Basin Couriers",
"waybill_number": "WB-31",
"expected_delivery_date": "2026-10-03"
},
"occurred_at": "2026-10-01T09:00:00Z"
},
)
response.raise_for_status()
print(response.json())
const token = "..."; // from POST /oauth/token/
const response = await fetch("https://api.dawatrack.com/partner-api/v1/events/", {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Idempotency-Key": crypto.randomUUID(),
"Content-Type": "application/json",
},
body: JSON.stringify({
"event_type": "SHIP",
"gtin": "06164004321562",
"batch_number": "BTH-2026-041",
"quantity": 2600,
"expiry_date": "2028-06-30",
"manufacture_date": "2026-06-01",
"destination_schema_name": "pharmacy_a",
"consignment": {
"number": "DESADV-0001",
"carrier_name": "Lake Basin Couriers",
"waybill_number": "WB-31",
"expected_delivery_date": "2026-10-03"
},
"occurred_at": "2026-10-01T09:00:00Z"
}),
});
console.log(await response.json());
Response fields
-
idinteger Read-onlyThe record's id.
-
event_typeenumThe kind of event.
Possible values:COMMISSIONSHIPRECEIVETRANSFERDISPENSEQUARANTINERELEASEAGGREGATEDISAGGREGATERECEIVE_LINKSHIP_ANSWERRECALL_ACKNOWLEDGMENTRECEIPT_ANSWERRETRACT -
gtinstringThe product's GS1 GTIN, as 14 digits.
-
batch_numberstringThe batch or lot number.
-
serial_numberstringThe unit's serial number.
-
ssccstringAn 18-digit GS1 Serial Shipping Container Code.
-
quantityintegerQuantity of units/items involved in this event (for batch-level or aggregated events).
-
expiry_datedate or nullThe lot's expiry date (GS1 AI 17). Optional. When the lot (GTIN and batch) is already on DawaTrack it must match the lot's, and a blank one takes the lot's; the first declaration with an expiry creates the lot. A raw_payload.expiry_date is still read for a lot not yet known.
-
manufacture_datedate or nullThe lot's manufacture date (GS1 AI 11). Optional, checked against the lot like expiry_date; not in the future, and before the expiry.
-
parent_eventinteger or nullParent event forming the distribution graph (e.g. COMMISSION/RECEIVE -> SHIP/DISPENSE).
-
corrects_eventinteger or nullEvent being corrected by this immutable record.
-
actor_idstringUser, system, or API actor ID that produced this event.
-
facility_idstringFacility node ID/schema in the network where the event occurred.
-
idempotency_keystringUnique key ensuring event write idempotency per reporter. Required for every new event.
-
occurred_atdatetimeDefaults to now if omitted.
-
raw_payloadobjectFor AGGREGATE events: {'children': [{'gtin', 'serial'}, ...]}.
-
destination_schema_namestringSHIP only, optional: the DawaTrack facility (its schema_name) receiving this shipment. When that facility receives the same GTIN and batch, its receipt is linked to this event.
-
destination_supplier_ppb_license_numberstringSHIP only, optional, for a partner linked to a supplier account: the PPB licence number of the approved DawaTrack supplier receiving this shipment. It confirms receipt on its Receiving screen. Use this or destination_schema_name, not both.
-
senderobjectRECEIVE only, optional: the sender of stock that came from outside DawaTrack, so there is no SHIP to name as parent_event. The receipt is where the graph picks the lot up. Not with parent_event; not for a sender on DawaTrack, whose SHIP you name instead.
-
namestring -
ppb_licencestring -
glnstring -
emailstringHow a recall reaches this party: kept on its party record, off the ledger, and only used to send it recall notices. An email and a phone are both required; the email is what a recall notice is sent to now. The phone is stored in E.164 (+254...); a Kenyan number may be given as 07... or 01...
-
phonestringHow a recall reaches this party: kept on its party record, off the ledger, and only used to send it recall notices. An email and a phone are both required; the email is what a recall notice is sent to now. The phone is stored in E.164 (+254...); a Kenyan number may be given as 07... or 01...
-
-
opening_balancebooleanRECEIVE only, optional: true when this is stock you held when you started on DawaTrack (opening stock, as an ERP's initial stock entry), so it came from no one on record: no parent_event, no sender. Once per lot, only for a lot you have no events on yet, and within 30 days of your first opening-stock receipt. The trace reads "Opening stock, declared by <you> on <date>".
Default:
False -
recipientobjectSHIP only, optional: the buyer of stock you sent outside DawaTrack, so a recall can reach it. Not with destination_schema_name or destination_supplier_ppb_license_number; not for a party on DawaTrack, which you name by those instead.
-
namestring -
ppb_licencestring -
emailstringHow a recall reaches this party: kept on its party record, off the ledger, and only used to send it recall notices. An email and a phone are both required; the email is what a recall notice is sent to now. The phone is stored in E.164 (+254...); a Kenyan number may be given as 07... or 01...
-
phonestringHow a recall reaches this party: kept on its party record, off the ledger, and only used to send it recall notices. An email and a phone are both required; the email is what a recall notice is sent to now. The phone is stored in E.164 (+254...); a Kenyan number may be given as 07... or 01...
-
-
consignmentobjectSHIP only, optional: the consignment (despatch advice) this shipment is a line of: your number, carrier, waybill, vehicle, driver and expected date. Without it, the SHIP is a one-line consignment DawaTrack numbers. The response's consignment_number names it.
-
numberstringYour own despatch advice number, unique among your consignments (1 to 40 letters, digits, '.', '_', '/' or '-'). SHIP events with the same number are lines of one consignment, to one receiver. Leave it out and DawaTrack numbers a one-line consignment.
-
referencestringYour order.
-
carrier_namestring -
waybill_numberstring -
vehicle_registrationstring -
driver_namestring -
driver_phonestring -
expected_delivery_datedate or null
-
-
consignment_numberstring Read-onlyThe consignment (despatch advice) a SHIP left on: its number, or blank.
-
created_atdatetime Read-onlyWhen the record was created.
-
recallobject or null Read-onlyThe open recall of this lot, or null. Recalled stock is received, not refused: put it on hold.
-
recall_idinteger -
actionenumquarantine: hold the stock; don't sell, dispense or ship it, and return it as the recall instructs. caution: a caution-in-use alert; the stock may be used following the instructions.
Possible values:quarantinecaution -
classificationstring -
reasonstring -
instructionsstringWhat facilities should do.
-
issued_bystring -
issued_atdatetime
-
Example response
{
"id": 42,
"event_type": "SHIP",
"gtin": "06164004321562",
"batch_number": "BTH-2026-041",
"serial_number": "SN-0007731",
"sscc": "106164004000007317",
"quantity": 2600,
"expiry_date": "2026-10-10",
"manufacture_date": "2026-10-10",
"parent_event": 1,
"corrects_event": 1,
"actor_id": "actor_id",
"facility_id": "pharmacy_a",
"idempotency_key": "idempotency_key",
"occurred_at": "2026-10-10T09:00:00Z",
"raw_payload": "raw_payload",
"destination_schema_name": "destination_schema_name",
"destination_supplier_ppb_license_number": "destination_supplier_ppb_license_number",
"sender": {
"name": "name",
"ppb_licence": "ppb_licence",
"gln": "gln",
"email": "email",
"phone": "phone"
},
"opening_balance": false,
"recipient": {
"name": "name",
"ppb_licence": "ppb_licence",
"email": "email",
"phone": "phone"
},
"consignment": {
"number": "number",
"reference": "reference",
"carrier_name": "carrier_name",
"waybill_number": "waybill_number",
"vehicle_registration": "vehicle_registration",
"driver_name": "driver_name",
"driver_phone": "driver_phone",
"expected_delivery_date": "2026-10-10"
},
"consignment_number": "consignment_number",
"created_at": "2026-10-10T09:00:00Z",
"recall": {
"recall_id": 42,
"action": "quarantine",
"classification": "classification",
"reason": "CONTAMINATION",
"instructions": "Quarantine the batch and await collection instructions.",
"issued_by": "issued_by",
"issued_at": "2026-10-10T09:00:00Z"
}
}
Status codes
201 | Created |
400 | The request is invalid, for example a malformed GTIN or a missing field |
401 | No valid access token |
403 | Your credential lacks the scope, partner type or environment this needs |
409 | Conflict: a request with this Idempotency-Key is in progress, or the record already exists |
429 | Rate limit exceeded |
Trace one of your events back to its origin
https://api.dawatrack.com/partner-api/v1/events/{id}/upstream/
The chain back from one of your events to where it began (a COMMISSION, or a first SHIP), nearest first.
batches:read
Limit 5,000 per day
Start from your own event only: another party's event, or an id that doesn't exist, returns 404.
Events you wrote (or your supplier account wrote) and the shipments you received are shown in full. Every other event on the chain is withheld: its type, when it happened and its place in the chain, with no id, party, quantity or location.
leads_to is the position of the event it leads to. truncated is true when the walk stopped at 20 facility hops. Requires batches:read.
Path parameters
-
idinteger Required
Example request
curl -X GET https://api.dawatrack.com/partner-api/v1/events/42/upstream/ \
-H "Authorization: Bearer $DAWATRACK_TOKEN"
import requests
token = "..." # from POST /oauth/token/
response = requests.get(
"https://api.dawatrack.com/partner-api/v1/events/42/upstream/",
headers={"Authorization": f"Bearer {token}"},
)
response.raise_for_status()
print(response.json())
const token = "..."; // from POST /oauth/token/
const response = await fetch("https://api.dawatrack.com/partner-api/v1/events/42/upstream/", {
method: "GET",
headers: {
Authorization: `Bearer ${token}`,
},
});
console.log(await response.json());
Response fields
-
eventinteger -
truncatedbooleanThe walk stopped at the depth limit (20 facility hops).
-
chainarray of objects-
positioninteger0 is the event asked about; the origin is last.
-
hops_backintegerFacility hops back from the event asked about.
-
leads_tointeger or nullThe position of the event this one leads to.
-
event_typestringThe kind of event.
-
occurred_atdatetimeWhen the event happened.
-
withheldbooleanAnother party's event: only its type and time are shown.
-
idintegerThe record's id.
-
gtinstringThe product's GS1 GTIN, as 14 digits.
-
batch_numberstringThe batch or lot number.
-
serial_numberstringThe unit's serial number.
-
ssccstringAn 18-digit GS1 Serial Shipping Container Code.
-
quantityinteger or nullThe number of units.
-
facility_idstring -
parent_eventinteger or null -
yoursbooleanYou wrote it (else you received it).
-
disputedbooleanA delivery a pharmacy recorded that its supplier disputes (SHIP only).
-
Example response
{
"event": 9123,
"truncated": false,
"chain": [
{
"position": 0,
"hops_back": 0,
"leads_to": null,
"event_type": "SHIP",
"occurred_at": "2026-10-20T09:15:00Z",
"withheld": false,
"id": 9123,
"gtin": "06164004321562",
"batch_number": "AMX-2026-041",
"serial_number": "",
"sscc": "",
"quantity": 120,
"facility_id": "WH-NAIROBI-01",
"parent_event": 9101,
"yours": true
},
{
"position": 1,
"hops_back": 1,
"leads_to": 0,
"event_type": "COMMISSION",
"occurred_at": "2026-10-02T06:00:00Z",
"withheld": true
}
]
}
Status codes
200 | OK |
401 | No valid access token |
403 | Your credential lacks the scope, partner type or environment this needs |
404 | Not found, or not visible to your credential |
429 | Rate limit exceeded |
Record events in bulk
https://api.dawatrack.com/partner-api/v1/events/bulk/
Submit up to 1,000 events in one request. They are processed in the background.
events:write
Limit 10 per hour
Returns 202 with a job_id. Each event is validated exactly like POST /events/, and failures are reported per event in the job's errors. An event that names no parent_event where one is needed fails with error_code PARENT_REQUIRED.
Every event must carry its own idempotency_key. The whole batch is refused, with no job created and nothing written, if any event has none (400, with offending_indexes), if two events share one (409, with collisions), or if one was already used by your events (409, with collisions naming the existing_event_id).
Resubmitting the same events with the same keys writes nothing new; events with new keys are a new submission. Events are no longer keyed by the job and their position when they have no key of their own: an integration that relied on that must send a key per event.
The Idempotency-Key header identifies the job: resubmitting with the same header returns the original job.
Request body
JSON. Send Content-Type: application/json.
-
eventsarray of objects RequiredUp to 1,000 events, each with the same fields as Record an event, and each with its own idempotency_key (required).
Example request
curl -X POST https://api.dawatrack.com/partner-api/v1/events/bulk/ \
-H "Authorization: Bearer $DAWATRACK_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"events": [
{
"idempotency_key": "commission-BTH-2026-041-SN-0007731",
"event_type": "COMMISSION",
"gtin": "06164004321562",
"batch_number": "BTH-2026-041",
"serial_number": "SN-0007731"
},
{
"idempotency_key": "commission-BTH-2026-041-SN-0007732",
"event_type": "COMMISSION",
"gtin": "06164004321562",
"batch_number": "BTH-2026-041",
"serial_number": "SN-0007732"
}
]
}'
import uuid
import requests
token = "..." # from POST /oauth/token/
response = requests.post(
"https://api.dawatrack.com/partner-api/v1/events/bulk/",
headers={"Authorization": f"Bearer {token}", "Idempotency-Key": str(uuid.uuid4())},
json={
"events": [
{
"idempotency_key": "commission-BTH-2026-041-SN-0007731",
"event_type": "COMMISSION",
"gtin": "06164004321562",
"batch_number": "BTH-2026-041",
"serial_number": "SN-0007731"
},
{
"idempotency_key": "commission-BTH-2026-041-SN-0007732",
"event_type": "COMMISSION",
"gtin": "06164004321562",
"batch_number": "BTH-2026-041",
"serial_number": "SN-0007732"
}
]
},
)
response.raise_for_status()
print(response.json())
const token = "..."; // from POST /oauth/token/
const response = await fetch("https://api.dawatrack.com/partner-api/v1/events/bulk/", {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Idempotency-Key": crypto.randomUUID(),
"Content-Type": "application/json",
},
body: JSON.stringify({
"events": [
{
"idempotency_key": "commission-BTH-2026-041-SN-0007731",
"event_type": "COMMISSION",
"gtin": "06164004321562",
"batch_number": "BTH-2026-041",
"serial_number": "SN-0007731"
},
{
"idempotency_key": "commission-BTH-2026-041-SN-0007732",
"event_type": "COMMISSION",
"gtin": "06164004321562",
"batch_number": "BTH-2026-041",
"serial_number": "SN-0007732"
}
]
}),
});
console.log(await response.json());
Response fields
-
job_idUUID Read-only -
statusenumPossible values:PENDINGPROCESSINGCOMPLETEDFAILEDPARTIAL -
total_eventsintegerEvents in the job.
-
processed_eventsintegerEvents processed so far.
-
succeeded_eventsintegerEvents recorded.
-
failed_eventsintegerEvents rejected.
-
errorsobjectOne entry per failed event: index, error_code, error_message and field_errors.
-
created_atdatetime Read-onlyWhen the record was created.
-
started_atdatetime or nullWhen processing started.
-
completed_atdatetime or nullWhen processing finished.
Example response
{
"job_id": "3f2b8c1e-7a41-4d2b-9a0e-6c5d8b1f2a30",
"status": "OPEN",
"total_events": 1,
"processed_events": 1,
"succeeded_events": 1,
"failed_events": 1,
"errors": "errors",
"created_at": "2026-10-10T09:00:00Z",
"started_at": "2026-10-10T09:00:00Z",
"completed_at": "2026-10-10T09:00:00Z"
}
Status codes
202 | Accepted: queued for processing |
400 | The request is invalid, for example a malformed GTIN or a missing field |
401 | No valid access token |
403 | Your credential lacks the scope, partner type or environment this needs |
409 | Conflict: a request with this Idempotency-Key is in progress, or the record already exists |
413 | Too many events in one request |
429 | Rate limit exceeded |
Fetch a bulk job
https://api.dawatrack.com/partner-api/v1/events/bulk/{job_id}/
The status of a bulk submission, with counts and per-event errors.
events:write
Limit 5,000 per day
Path parameters
-
job_idUUID Required
Example request
curl -X GET https://api.dawatrack.com/partner-api/v1/events/bulk/3f2b8c1e-7a41-4d2b-9a0e-6c5d8b1f2a30/ \
-H "Authorization: Bearer $DAWATRACK_TOKEN"
import requests
token = "..." # from POST /oauth/token/
response = requests.get(
"https://api.dawatrack.com/partner-api/v1/events/bulk/3f2b8c1e-7a41-4d2b-9a0e-6c5d8b1f2a30/",
headers={"Authorization": f"Bearer {token}"},
)
response.raise_for_status()
print(response.json())
const token = "..."; // from POST /oauth/token/
const response = await fetch("https://api.dawatrack.com/partner-api/v1/events/bulk/3f2b8c1e-7a41-4d2b-9a0e-6c5d8b1f2a30/", {
method: "GET",
headers: {
Authorization: `Bearer ${token}`,
},
});
console.log(await response.json());
Response fields
-
job_idUUID Read-only -
statusenumPossible values:PENDINGPROCESSINGCOMPLETEDFAILEDPARTIAL -
total_eventsintegerEvents in the job.
-
processed_eventsintegerEvents processed so far.
-
succeeded_eventsintegerEvents recorded.
-
failed_eventsintegerEvents rejected.
-
errorsobjectOne entry per failed event: index, error_code, error_message and field_errors.
-
created_atdatetime Read-onlyWhen the record was created.
-
started_atdatetime or nullWhen processing started.
-
completed_atdatetime or nullWhen processing finished.
Example response
{
"job_id": "3f2b8c1e-7a41-4d2b-9a0e-6c5d8b1f2a30",
"status": "OPEN",
"total_events": 1,
"processed_events": 1,
"succeeded_events": 1,
"failed_events": 1,
"errors": "errors",
"created_at": "2026-10-10T09:00:00Z",
"started_at": "2026-10-10T09:00:00Z",
"completed_at": "2026-10-10T09:00:00Z"
}
Status codes
200 | OK |
401 | No valid access token |
403 | Your credential lacks the scope, partner type or environment this needs |
404 | Not found, or not visible to your credential |
429 | Rate limit exceeded |
Partner API v1. The API reference is generated from the API's own code.