Developer overview
API reference14 minute readAPI v1

Sales order REST API

Poll submitted orders, acknowledge ERP receipt and return fulfilment status without duplicate processing.

Browse developer docs

The Order API lets external systems retrieve orders placed through SalesPro Hub and push status updates back. This is the primary integration point for ERP systems like Sage and Pastel.

Typical Integration Flow

text
1. External system polls for new orders     GET  /api/v1/orders?status=pending&acknowledged=false
2. External system creates internal order    (your ERP logic)
3. External system acknowledges receipt      POST /api/v1/orders/{orderNumber}/acknowledge
4. External system updates status            PUT  /api/v1/orders/{orderNumber}/status

Endpoints

List Orders

text
GET /api/v1/orders

Permission required: orders:read

Retrieve a paginated list of orders with optional filters. This is your primary polling endpoint.

Query Parameters

ParameterTypeDescription
statusstringFilter by status: pending, confirmed, processing, delivered, cancelled
typestringFilter by type: order, quote
acknowledgedstringtrue or false — filter by acknowledgement status
updated_sinceISO 8601Only return orders updated after this timestamp
updated_since_idintegerTie-breaker returned in meta.next_cursor; only send with updated_since
from_datedateOrders with order_date on or after this date
to_datedateOrders with order_date on or before this date
per_pageintegerResults per page (1-100, default 50)

Drafts are never returned by the external Order API. Incremental requests are sorted by updated_at, then internal ID, so callers can safely resume when multiple orders share the same timestamp.

Example: Poll for New Unprocessed Orders

bash
curl -X GET "https://portal.salesrepsoftware.co.za/api/v1/orders?status=pending&acknowledged=false" \
  -H "X-API-Key: sk_your_key" \
  -H "Accept: application/json"

Example: Incremental Sync

Get only orders that changed since your last sync:

bash
curl -X GET "https://portal.salesrepsoftware.co.za/api/v1/orders?updated_since=2026-02-09T10:00:00Z" \
  -H "X-API-Key: sk_your_key" \
  -H "Accept: application/json"

Response

json
{
  "success": true,
  "data": [
    {
      "order_number": "ORD-20260209-0001",
      "status": "pending",
      "type": "order",
      "order_date": "2026-02-09",
      "delivery_date": "2026-02-16",
      "customer": {
        "name": "ABC Trading (Pty) Ltd",
        "contact_person": "John Smith",
        "email": "john@abctrading.co.za",
        "phone": "0821234567"
      },
      "sales_rep": {
        "name": "Jane Doe"
      },
      "subtotal": "10000.00",
      "vat_rate": "15.00",
      "vat_amount": "1500.00",
      "discount_amount": "0.00",
      "total": "11500.00",
      "delivery_address": "123 Main Road, Sandton, 2196",
      "notes": "Deliver before 10am",
      "payment_status": "unpaid",
      "items": [
        {
          "sku": "WDG-001",
          "name": "Widget A",
          "quantity": 50,
          "unit_price": "200.00",
          "discount_percent": "0.00",
          "line_total": "10000.00"
        }
      ],
      "acknowledged_at": null,
      "external_reference": null,
      "created_at": "2026-02-09T08:30:00+02:00",
      "updated_at": "2026-02-09T08:30:00+02:00"
    }
  ],
  "meta": {
    "total": 42,
    "page": 1,
    "per_page": 50,
    "last_page": 1,
    "next_cursor": {
      "updated_since": "2026-02-09T08:30:00.000000Z",
      "updated_since_id": 412
    }
  }
}

Get Single Order

text
GET /api/v1/orders/{orderNumber}

Permission required: orders:read

Retrieve a single order by its order number.

Example

bash
curl -X GET "https://portal.salesrepsoftware.co.za/api/v1/orders/ORD-20260209-0001" \
  -H "X-API-Key: sk_your_key" \
  -H "Accept: application/json"

Response

json
{
  "success": true,
  "data": {
    "order_number": "ORD-20260209-0001",
    "status": "pending",
    "type": "order",
    "order_date": "2026-02-09",
    "delivery_date": "2026-02-16",
    "customer": {
      "name": "ABC Trading (Pty) Ltd",
      "contact_person": "John Smith",
      "email": "john@abctrading.co.za",
      "phone": "0821234567"
    },
    "sales_rep": {
      "name": "Jane Doe"
    },
    "subtotal": "10000.00",
    "vat_rate": "15.00",
    "vat_amount": "1500.00",
    "discount_amount": "0.00",
    "total": "11500.00",
    "delivery_address": "123 Main Road, Sandton, 2196",
    "notes": "Deliver before 10am",
    "payment_status": "unpaid",
    "items": [
      {
        "sku": "WDG-001",
        "name": "Widget A",
        "quantity": 50,
        "unit_price": "200.00",
        "discount_percent": "0.00",
        "line_total": "10000.00"
      }
    ],
    "acknowledged_at": null,
    "external_reference": null,
    "created_at": "2026-02-09T08:30:00+02:00",
    "updated_at": "2026-02-09T08:30:00+02:00"
  }
}

Error: Order Not Found

json
{
  "success": false,
  "error": "Order not found"
}

Acknowledge Order

text
POST /api/v1/orders/{orderNumber}/acknowledge

Permission required: orders:write

Mark an order as received by your external system. This sets the acknowledged_at timestamp and optionally stores your system's reference number.

Use acknowledgement to track which orders you've already processed. Then poll with ?acknowledged=false to only get new, unprocessed orders.

Acknowledgement is idempotent: replaying the same request preserves the first timestamp. Reusing the order with a different non-empty external reference returns HTTP 409 instead of silently relinking it.

Request Body

FieldTypeRequiredDescription
external_referencestringNoYour system's reference number (e.g., Sage invoice number). Max 255 characters.

Example

bash
curl -X POST "https://portal.salesrepsoftware.co.za/api/v1/orders/ORD-20260209-0001/acknowledge" \
  -H "X-API-Key: sk_your_key" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{"external_reference": "SAGE-INV-00451"}'

Response

json
{
  "success": true,
  "data": {
    "order_number": "ORD-20260209-0001",
    "acknowledged_at": "2026-02-09T10:15:00+02:00",
    "external_reference": "SAGE-INV-00451"
  },
  "message": "Order acknowledged successfully"
}

Update Order Status

text
PUT /api/v1/orders/{orderNumber}/status

Permission required: orders:write

Update an order's status from your external system. For example, mark an order as confirmed after processing in your ERP, or mark as delivered after dispatch.

Request Body

FieldTypeRequiredDescription
statusstringYesNew status: confirmed, processing, delivered, or cancelled
external_referencestringNoYour system's reference number. Max 255 characters.
notesstringNoAdditional notes (used as cancellation reason if cancelling). Max 1000 characters.

Valid Status Transitions

FromAllowed Transitions
pendingconfirmed, cancelled
confirmedprocessing, delivered, cancelled
processingdelivered, cancelled

delivered and cancelled are terminal — they cannot be changed.

Replaying the current status is safe and does not emit another status event or deduct/release inventory twice. When the tenant uses reserve_and_deduct, moving an order to delivered deducts its reservation and moving it to cancelled releases the reservation. Tenants whose ERP is the inventory source of truth should select the inventory policy that avoids deducting the same fulfilment in both systems.

Example: Confirm an Order

bash
curl -X PUT "https://portal.salesrepsoftware.co.za/api/v1/orders/ORD-20260209-0001/status" \
  -H "X-API-Key: sk_your_key" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{"status": "confirmed", "external_reference": "SAGE-INV-00451"}'

Response

json
{
  "success": true,
  "data": {
    "order_number": "ORD-20260209-0001",
    "previous_status": "pending",
    "new_status": "confirmed",
    "external_reference": "SAGE-INV-00451"
  },
  "message": "Order status updated to 'confirmed'"
}

Error: Invalid Transition

json
{
  "success": false,
  "error": "Cannot transition from 'delivered' to 'confirmed'"
}

Order Statuses

StatusDescription
draftBeing composed by sales rep (not visible via API)
pendingSubmitted and awaiting approval
confirmedApproved and ready for fulfilment
processingBeing prepared/dispatched
deliveredSuccessfully delivered (terminal)
cancelledCancelled (terminal)

Order Types

TypeDescription
orderA confirmed purchase order
quoteA price quotation (can be converted to an order)

Payment Statuses

StatusDescription
unpaidNo payment received
partialPartial payment received
paidFully paid

For most integrations, poll every 5-15 minutes:

text
GET /api/v1/orders?status=pending&acknowledged=false&per_page=100

For each order returned:

  1. Create the order in your external system.
  2. Call POST /acknowledge with your external reference number.
  3. The order won't appear in subsequent polls (filtered by acknowledged=false).

For incremental sync (catching status changes and updates):

text
GET /api/v1/orders?updated_since=2026-02-09T10:00:00Z

Store and send the complete meta.next_cursor object:

json
{
  "updated_since": "2026-02-09T10:00:00.000000Z",
  "updated_since_id": 412
}

Using only updated_at can skip records when several orders have the same timestamp. Begin each cursor request at page 1; the cursor itself advances the result set.

Build against the real API

Professional API features are included in the 14-day trial.