Skip to main content

Purchase orders

Orders pharmacies placed with you: confirm, reject, and declare what you're delivering.

List orders

GET https://api.dawatrack.com/partner-api/v1/purchase-orders/

Orders pharmacies on DawaTrack placed with your supplier account, newest first.

Scope orders:read Limit 5,000 per day

Your credential must belong to an API account linked to a supplier account; otherwise 403. Needs orders:read.

Filter with status: SENT (waiting for you), CONFIRMED, PARTIALLY_RECEIVED, RECEIVED or CANCELLED. The order.* webhooks tell you when a new order arrives.

Query parameters

  • ordering string Optional

    Which field to use when ordering the results.

  • page integer Optional

    A page number within the paginated result set.

  • page_size integer Optional

    Number of results to return per page.

  • search string Optional

    A search term.

  • status enum Optional
    Possible values: CANCELLEDCONFIRMEDPARTIALLY_RECEIVEDRECEIVEDSENT

Example request

curl -X GET https://api.dawatrack.com/partner-api/v1/purchase-orders/ \
  -H "Authorization: Bearer $DAWATRACK_TOKEN"
import requests

token = "..."  # from POST /oauth/token/
response = requests.get(
    "https://api.dawatrack.com/partner-api/v1/purchase-orders/",
    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/purchase-orders/", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${token}`,
  },
});
console.log(await response.json());

Response fields

A page of results. These are the fields of each item in results. See Pagination.

  • order_id integer
  • po_number string
  • pharmacy_name string

    The facility's name.

  • status string
  • order_date date
  • expected_delivery date or null
  • total_amount string
  • confirmed_delivery_date date or null
  • carrier_name string
  • tracking_reference string
  • notes string
  • lines array of objects
    • line_id integer
    • medicine_name string

      The product's name.

    • quantity_ordered integer
    • unit_price string
    • quantity_confirmed integer
    • batch_number string

      The batch or lot number.

    • expiry_date date or null

      The batch's expiry date.

    • note string

Example response

JSON
{
  "count": 1,
  "next": null,
  "previous": null,
  "results": [
    {
      "order_id": 1,
      "po_number": "po_number",
      "pharmacy_name": "Pharmacy A",
      "status": "OPEN",
      "order_date": "2026-10-10",
      "expected_delivery": "2026-10-10",
      "total_amount": "total_amount",
      "confirmed_delivery_date": "2026-10-10",
      "carrier_name": "carrier_name",
      "tracking_reference": "tracking_reference",
      "notes": "notes",
      "lines": [
        {}
      ]
    }
  ]
}

Status codes

200OK
401No valid access token
403Your credential lacks the scope, partner type or environment this needs
429Rate limit exceeded

Get an order

GET https://api.dawatrack.com/partner-api/v1/purchase-orders/{id}/

One order with its lines; each line has a line_id you declare delivery against.

Scope orders:read Limit 5,000 per day

An order placed with another supplier is 404.

Path parameters

  • id integer Required

Example request

curl -X GET https://api.dawatrack.com/partner-api/v1/purchase-orders/42/ \
  -H "Authorization: Bearer $DAWATRACK_TOKEN"
import requests

token = "..."  # from POST /oauth/token/
response = requests.get(
    "https://api.dawatrack.com/partner-api/v1/purchase-orders/42/",
    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/purchase-orders/42/", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${token}`,
  },
});
console.log(await response.json());

Response fields

  • order_id integer
  • po_number string
  • pharmacy_name string

    The facility's name.

  • status string
  • order_date date
  • expected_delivery date or null
  • total_amount string
  • confirmed_delivery_date date or null
  • carrier_name string
  • tracking_reference string
  • notes string
  • lines array of objects
    • line_id integer
    • medicine_name string

      The product's name.

    • quantity_ordered integer
    • unit_price string
    • quantity_confirmed integer
    • batch_number string

      The batch or lot number.

    • expiry_date date or null

      The batch's expiry date.

    • note string

Example response

JSON
{
  "order_id": 1,
  "po_number": "po_number",
  "pharmacy_name": "Pharmacy A",
  "status": "OPEN",
  "order_date": "2026-10-10",
  "expected_delivery": "2026-10-10",
  "total_amount": "total_amount",
  "confirmed_delivery_date": "2026-10-10",
  "carrier_name": "carrier_name",
  "tracking_reference": "tracking_reference",
  "notes": "notes",
  "lines": [
    {
      "line_id": 1,
      "medicine_name": "Amoxicillin 500 mg capsules",
      "quantity_ordered": 1,
      "unit_price": "unit_price",
      "quantity_confirmed": 1,
      "batch_number": "BTH-2026-041",
      "expiry_date": "2026-10-10",
      "note": "Contract CP-2026-11"
    }
  ]
}

Status codes

200OK
401No valid access token
403Your credential lacks the scope, partner type or environment this needs
429Rate limit exceeded

Confirm an order

POST https://api.dawatrack.com/partner-api/v1/purchase-orders/{id}/confirm/

Accept an order that is waiting for you (SENT).

Scope orders:write Production credentials only Limit 5,000 per day

The pharmacy sees it confirmed. An order that isn't waiting is 400. Needs orders:write; production credentials only.

Path parameters

  • id integer Required

Example request

curl -X POST https://api.dawatrack.com/partner-api/v1/purchase-orders/42/confirm/ \
  -H "Authorization: Bearer $DAWATRACK_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)"
import uuid
import requests

token = "..."  # from POST /oauth/token/
response = requests.post(
    "https://api.dawatrack.com/partner-api/v1/purchase-orders/42/confirm/",
    headers={"Authorization": f"Bearer {token}", "Idempotency-Key": str(uuid.uuid4())},
)
response.raise_for_status()
print(response.json())
const token = "..."; // from POST /oauth/token/
const response = await fetch("https://api.dawatrack.com/partner-api/v1/purchase-orders/42/confirm/", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${token}`,
    "Idempotency-Key": crypto.randomUUID(),
  },
});
console.log(await response.json());

Response fields

  • order_id integer
  • po_number string
  • pharmacy_name string

    The facility's name.

  • status string
  • order_date date
  • expected_delivery date or null
  • total_amount string
  • confirmed_delivery_date date or null
  • carrier_name string
  • tracking_reference string
  • notes string
  • lines array of objects
    • line_id integer
    • medicine_name string

      The product's name.

    • quantity_ordered integer
    • unit_price string
    • quantity_confirmed integer
    • batch_number string

      The batch or lot number.

    • expiry_date date or null

      The batch's expiry date.

    • note string

Example response

JSON
{
  "order_id": 1,
  "po_number": "po_number",
  "pharmacy_name": "Pharmacy A",
  "status": "OPEN",
  "order_date": "2026-10-10",
  "expected_delivery": "2026-10-10",
  "total_amount": "total_amount",
  "confirmed_delivery_date": "2026-10-10",
  "carrier_name": "carrier_name",
  "tracking_reference": "tracking_reference",
  "notes": "notes",
  "lines": [
    {
      "line_id": 1,
      "medicine_name": "Amoxicillin 500 mg capsules",
      "quantity_ordered": 1,
      "unit_price": "unit_price",
      "quantity_confirmed": 1,
      "batch_number": "BTH-2026-041",
      "expiry_date": "2026-10-10",
      "note": "Contract CP-2026-11"
    }
  ]
}

Status codes

200OK
400The request is invalid, for example a malformed GTIN or a missing field
401No valid access token
403Your credential lacks the scope, partner type or environment this needs
409Conflict: a request with this Idempotency-Key is in progress, or the record already exists
429Rate limit exceeded

Reject an order

POST https://api.dawatrack.com/partner-api/v1/purchase-orders/{id}/reject/

Turn down an order that is waiting for you; the pharmacy sees it cancelled, with your reason.

Scope orders:write Production credentials only Limit 5,000 per day

Path parameters

  • id integer Required

Request body

JSON. Send Content-Type: application/json.

  • reason string Optional

Example request

curl -X POST https://api.dawatrack.com/partner-api/v1/purchase-orders/42/reject/ \
  -H "Authorization: Bearer $DAWATRACK_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "reason": "Out of stock until next month"
  }'
import uuid
import requests

token = "..."  # from POST /oauth/token/
response = requests.post(
    "https://api.dawatrack.com/partner-api/v1/purchase-orders/42/reject/",
    headers={"Authorization": f"Bearer {token}", "Idempotency-Key": str(uuid.uuid4())},
    json={
      "reason": "Out of stock until next month"
    },
)
response.raise_for_status()
print(response.json())
const token = "..."; // from POST /oauth/token/
const response = await fetch("https://api.dawatrack.com/partner-api/v1/purchase-orders/42/reject/", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${token}`,
    "Idempotency-Key": crypto.randomUUID(),
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "reason": "Out of stock until next month"
  }),
});
console.log(await response.json());

Response fields

  • order_id integer
  • po_number string
  • pharmacy_name string

    The facility's name.

  • status string
  • order_date date
  • expected_delivery date or null
  • total_amount string
  • confirmed_delivery_date date or null
  • carrier_name string
  • tracking_reference string
  • notes string
  • lines array of objects
    • line_id integer
    • medicine_name string

      The product's name.

    • quantity_ordered integer
    • unit_price string
    • quantity_confirmed integer
    • batch_number string

      The batch or lot number.

    • expiry_date date or null

      The batch's expiry date.

    • note string

Example response

JSON
{
  "order_id": 1,
  "po_number": "po_number",
  "pharmacy_name": "Pharmacy A",
  "status": "OPEN",
  "order_date": "2026-10-10",
  "expected_delivery": "2026-10-10",
  "total_amount": "total_amount",
  "confirmed_delivery_date": "2026-10-10",
  "carrier_name": "carrier_name",
  "tracking_reference": "tracking_reference",
  "notes": "notes",
  "lines": [
    {
      "line_id": 1,
      "medicine_name": "Amoxicillin 500 mg capsules",
      "quantity_ordered": 1,
      "unit_price": "unit_price",
      "quantity_confirmed": 1,
      "batch_number": "BTH-2026-041",
      "expiry_date": "2026-10-10",
      "note": "Contract CP-2026-11"
    }
  ]
}

Status codes

200OK
400The request is invalid, for example a malformed GTIN or a missing field
401No valid access token
403Your credential lacks the scope, partner type or environment this needs
409Conflict: a request with this Idempotency-Key is in progress, or the record already exists
429Rate limit exceeded

Declare delivery

POST https://api.dawatrack.com/partner-api/v1/purchase-orders/{id}/delivery/

Say what you're sending: per line the units, batch and expiry, and the delivery date, carrier and tracking.

Scope orders:write Production credentials only Limit 5,000 per day

Each line with a batch_number and a quantity becomes a SHIP event in the traceability ledger; when the pharmacy receives that line, its receipt links to it. Declaring again with a different batch or quantity writes a correcting event.

Quantities are capped at what was ordered. Lines you don't list keep what you declared before; a line_id not on the order is 400.

A product you make whose PPB registration is on hold can't be declared (400): set its quantity to 0 to deliver the rest.

Declaring on an order that was waiting confirms it. Same rules as the supplier portal.

Path parameters

  • id integer Required

Request body

JSON. Send Content-Type: application/json.

  • lines array of objects Required

    Lines not listed keep what was declared before.

    • line_id integer Required
    • quantity integer Required

      Units sent; capped at what was ordered.

    • batch_number string Optional

      The batch or lot number.

    • expiry_date date or null Optional

      The batch's expiry date.

    • note string Optional
  • delivery_date date or null Optional
  • carrier_name string Optional
  • tracking_reference string Optional
  • notes string Optional

Example request

curl -X POST https://api.dawatrack.com/partner-api/v1/purchase-orders/42/delivery/ \
  -H "Authorization: Bearer $DAWATRACK_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "lines": [
      {
        "line_id": 123,
        "quantity": 20,
        "batch_number": "BTH-2026-041",
        "expiry_date": "2028-01-31"
      }
    ],
    "delivery_date": "2026-11-02",
    "carrier_name": "G4S",
    "tracking_reference": "TRK-99123"
  }'
import uuid
import requests

token = "..."  # from POST /oauth/token/
response = requests.post(
    "https://api.dawatrack.com/partner-api/v1/purchase-orders/42/delivery/",
    headers={"Authorization": f"Bearer {token}", "Idempotency-Key": str(uuid.uuid4())},
    json={
      "lines": [
        {
          "line_id": 123,
          "quantity": 20,
          "batch_number": "BTH-2026-041",
          "expiry_date": "2028-01-31"
        }
      ],
      "delivery_date": "2026-11-02",
      "carrier_name": "G4S",
      "tracking_reference": "TRK-99123"
    },
)
response.raise_for_status()
print(response.json())
const token = "..."; // from POST /oauth/token/
const response = await fetch("https://api.dawatrack.com/partner-api/v1/purchase-orders/42/delivery/", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${token}`,
    "Idempotency-Key": crypto.randomUUID(),
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "lines": [
      {
        "line_id": 123,
        "quantity": 20,
        "batch_number": "BTH-2026-041",
        "expiry_date": "2028-01-31"
      }
    ],
    "delivery_date": "2026-11-02",
    "carrier_name": "G4S",
    "tracking_reference": "TRK-99123"
  }),
});
console.log(await response.json());

Response fields

  • order_id integer
  • po_number string
  • pharmacy_name string

    The facility's name.

  • status string
  • order_date date
  • expected_delivery date or null
  • total_amount string
  • confirmed_delivery_date date or null
  • carrier_name string
  • tracking_reference string
  • notes string
  • lines array of objects
    • line_id integer
    • medicine_name string

      The product's name.

    • quantity_ordered integer
    • unit_price string
    • quantity_confirmed integer
    • batch_number string

      The batch or lot number.

    • expiry_date date or null

      The batch's expiry date.

    • note string

Example response

JSON
{
  "order_id": 1,
  "po_number": "po_number",
  "pharmacy_name": "Pharmacy A",
  "status": "OPEN",
  "order_date": "2026-10-10",
  "expected_delivery": "2026-10-10",
  "total_amount": "total_amount",
  "confirmed_delivery_date": "2026-10-10",
  "carrier_name": "carrier_name",
  "tracking_reference": "tracking_reference",
  "notes": "notes",
  "lines": [
    {
      "line_id": 1,
      "medicine_name": "Amoxicillin 500 mg capsules",
      "quantity_ordered": 1,
      "unit_price": "unit_price",
      "quantity_confirmed": 1,
      "batch_number": "BTH-2026-041",
      "expiry_date": "2026-10-10",
      "note": "Contract CP-2026-11"
    }
  ]
}

Status codes

200OK
400The request is invalid, for example a malformed GTIN or a missing field
401No valid access token
403Your credential lacks the scope, partner type or environment this needs
409Conflict: a request with this Idempotency-Key is in progress, or the record already exists
429Rate limit exceeded

Partner API v1. The API reference is generated from the API's own code.