Skip to content
SIBISIBI Developers
Esc
navigateopen⌘Jpreview
On this page

Draft Orders Guide

Preview an order with a draft order, then place it

A draft order prices an order without placing it. It takes the same body as POST /orders and returns what that order would resolve to — the distribution center, fulfillment method, delivery date, and payment method it would get, the alternatives available for each, per-line availability, options, addons, and warranties, and the full pricing breakdown. A draft can then be placed by id, so the order that ships is the one that was quoted.

Benefits

  • Quote before you commit: See the total, taxes, and fees before anything is placed
  • Discover the choices: Every available fulfillment method, delivery date, payment method, addon, and warranty comes back resolved for the order in hand
  • Catch failures early: Validation runs exactly as it does at placement, so a bad supplier, SKU, or option fails on the draft instead of on the order
  • Quote, then place it: Place the draft by id and the order takes exactly the options and pricing the draft resolved — no body to reassemble and nothing to drift

Core Concepts

Draft Order

A priced, validated preview of an order. It reserves nothing and charges nothing.

Resolved Defaults

The distribution center, fulfillment method, delivery date, and payment method the order would get when the request leaves them unspecified.

Availability

Per-line stock status in the draft’s distribution center: IN_STOCK, OUT_OF_STOCK, SUBSTITUTION_ONLY, UNAVAILABLE, or UNKNOWN.

Pricing

Subtotal, tax, fees, and discounts, plus the totalPriceCents the order would charge.

Creating a Draft Order

POST https://api.sibipro.com/draft-orders with a create:draft-orders scoped REST API token. The body is the POST /orders body — at minimum a supplier, an address, contactInfo, one or more lineItems, and a paymentMethodId.

curl \
  --request POST \
  --header 'Authorization: Bearer <YOUR_API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
    "supplier": "ge",
    "address": {
      "line1": "1630 W Guadalupe Rd",
      "city": "Gilbert",
      "stateOrProvince": "AZ",
      "postalCode": "85233"
    },
    "contactInfo": {
      "firstName": "John",
      "lastName": "Doe",
      "email": "john.doe@example.com",
      "phone": "1234567890"
    },
    "lineItems": [{ "sku": "GDF510PSRSS", "quantity": 1 }],
    "paymentMethodId": "MANUFACTURER_CREDIT"
  }' \
  https://api.sibipro.com/draft-orders
const response = await fetch('https://api.sibipro.com/draft-orders', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${yourApiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    supplier: 'ge',
    address: {
      line1: '1630 W Guadalupe Rd',
      city: 'Gilbert',
      stateOrProvince: 'AZ',
      postalCode: '85233',
    },
    contactInfo: {
      firstName: 'John',
      lastName: 'Doe',
      email: 'john.doe@example.com',
      phone: '1234567890',
    },
    lineItems: [{ sku: 'GDF510PSRSS', quantity: 1 }],
    paymentMethodId: 'MANUFACTURER_CREDIT',
  }),
});
const draftOrder = await response.json();

A successful call returns 201 with the draft order:

{
  "id": "01J9X0N3K7Q2VWY5B8ZC4TDR6H",
  "createdAt": "2026-08-31T00:00:00.000Z",
  "supplier": "ge",
  "address": {
    "line1": "1630 W Guadalupe Rd",
    "line2": null,
    "city": "Gilbert",
    "stateOrProvince": "AZ",
    "postalCode": "85233",
    "country": "USA"
  },
  "contactInfo": {
    "firstName": "John",
    "lastName": "Doe",
    "email": "john.doe@example.com",
    "phone": "1234567890"
  },
  "poNumber": null,
  "specialInstructions": null,
  "lineItems": [
    {
      "sku": "GDF510PSRSS",
      "name": "GE Dishwasher",
      "subtitle": "Front Control with Plastic Interior",
      "imageUrl": "https://images.sibipro.com/GDF510PSRSS.jpg",
      "quantity": 1,
      "unitOfMeasure": "Each",
      "quantityPerBaseUnit": 1,
      "baseUnitOfMeasure": "Each",
      "priceCents": 54900,
      "availabilityStatus": "IN_STOCK",
      "options": [],
      "attributes": [{ "name": "finish", "value": "Stainless Steel" }],
      "addons": [],
      "availableAddons": [{ "id": "haul-away", "title": "Haul Away", "priceCents": 2500 }],
      "availableWarranties": [
        {
          "sku": "GE-WARR-3YR",
          "name": "3 Year Protection Plan",
          "description": "Parts and labor for three years",
          "manufacturer": "GE",
          "priceCents": 9900
        }
      ],
      "selectedWarranty": null
    }
  ],
  "distributionCenter": {
    "id": "ge-dc-phx",
    "name": "Phoenix DC",
    "storeNumber": "0412",
    "address": {
      "line1": "4000 E Air Ln",
      "line2": null,
      "city": "Phoenix",
      "stateOrProvince": "AZ",
      "postalCode": "85034",
      "country": "USA"
    }
  },
  "fulfillmentMethod": {
    "id": "sibi-sibi-default-delivery",
    "title": "Standard Delivery",
    "description": null,
    "type": "DELIVERY",
    "availableDates": ["2026-09-01", "2026-09-02", "2026-09-03"]
  },
  "availableFulfillmentMethods": [
    {
      "id": "sibi-sibi-default-delivery",
      "title": "Standard Delivery",
      "description": null,
      "type": "DELIVERY",
      "availableDates": ["2026-09-01", "2026-09-02", "2026-09-03"]
    },
    {
      "id": "sibi-sibi-default-pickup",
      "title": "Will Call",
      "description": "Pick up at the distribution center",
      "type": "PICKUP",
      "availableDates": ["2026-09-01"]
    }
  ],
  "requestedDeliveryDate": "2026-09-01",
  "paymentMethodId": "MANUFACTURER_CREDIT",
  "availablePaymentMethods": [
    {
      "id": "MANUFACTURER_CREDIT",
      "type": "MANUFACTURER_CREDIT",
      "description": "On account",
      "last4": null
    }
  ],
  "pricing": {
    "subtotalCents": 54900,
    "taxCents": 4392,
    "totalPriceCents": 62292,
    "fees": [{ "name": "Delivery fee", "amountCents": 3000 }],
    "discounts": []
  },
  "subscribers": []
}

Fetching a Draft

GET https://api.sibipro.com/draft-orders/{id} reads a draft back, with a read:draft-orders scoped token. The response is the body POST /draft-orders returned, so a caller that drafts, reads it back, then places it handles a single shape.

curl \
  --request GET \
  --header 'Authorization: Bearer <YOUR_API_KEY>' \
  https://api.sibipro.com/draft-orders/<DRAFT_ORDER_ID>
const response = await fetch(`https://api.sibipro.com/draft-orders/${draftOrderId}`, {
  headers: { Authorization: `Bearer ${yourApiKey}` },
});
const draftOrder = await response.json();

Nothing is repriced on read: the draft comes back as it was resolved, so it can describe availability or pricing that has since changed and still be rejected at placement.

Reading the Draft

The draft answers the questions you would otherwise have to guess at before placing the order.

What you want to know Where to look
What will this cost? pricing.totalPriceCents, broken out into subtotalCents, taxCents, fees, and discounts
Is it in stock? lineItems[].availabilityStatus
When can it arrive? fulfillmentMethod.availableDates, or availableFulfillmentMethods[].availableDates for the other methods
How else can it be fulfilled? availableFulfillmentMethods — each id is a fulfillmentMethodId
How can it be paid for? availablePaymentMethods — each id is a paymentMethodId
Where would it ship from? distributionCenter — its id is a distributionCenterId
What can be added to a line? lineItems[].availableAddons (each id is an addonIds entry) and lineItems[].availableWarranties (each sku is a warrantySku)

Prices are integer cents, dates are ISO 8601, and quantityPerBaseUnit × quantity gives the total in baseUnitOfMeasure for products sold by area or length.

Placing the Draft

POST https://api.sibipro.com/draft-orders/{id}/order places the order the draft describes, with a create:from-draft:orders scoped token. The draft id in the path is the request — nothing about the order can be changed here, so the order that ships is the one the draft priced.

The body is optional and carries only an idempotencyKey. Send one: resubmitting the same draft with the same key within 5 minutes returns the order already placed instead of placing a second one. A 5xx response or a timeout does not prove the order was not placed, so retry only with the same key.

curl \
  --request POST \
  --header 'Authorization: Bearer <YOUR_API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{"idempotencyKey": "b8f0e6d2-1c3a-4f5e-9a7b-0d2c4e6f8a1b"}' \
  https://api.sibipro.com/draft-orders/<DRAFT_ORDER_ID>/order
const response = await fetch(`https://api.sibipro.com/draft-orders/${draftOrder.id}/order`, {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${yourApiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ idempotencyKey }),
});
const order = await response.json();

A successful call returns 201 with the same body POST /orders returns, so a caller that drafts-then-places handles one response shape:

{
  "id": "SIBI-12345678",
  "orderUrl": "https://web.sibipro.com/orders/SIBI-12345678",
  "warrantyOrderId": null,
  "warrantyOrderUrl": null
}

Changing an order before placing it

A draft is fixed. To order something different — another fulfillment method, delivery date, payment method, distribution center, addon, or warranty — copy the chosen identifier out of the draft into the same body you drafted with and create a new draft, then place that one:

Draft

Post the order body to /draft-orders and read the resolved defaults and alternatives

Redraft to change

To change anything, copy the chosen fulfillmentMethodId, requestedDeliveryDate, paymentMethodId, distributionCenterId, addonIds, or warrantySku into the body and draft again

Place

Post to /draft-orders/{id}/order with an idempotencyKey

A draft becomes exactly one order. Posting to a draft that already has one is refused with 409 DRAFT_ORDER_ALREADY_PLACED, and the message names the order it became so a caller that lost the response can pick that order up instead of retrying.

Errors

Validation runs on the draft exactly as it does at placement, so both endpoints return the same 400 codes as POST /ordersVALIDATION_ERROR, INVALID_SUPPLIER, PRODUCTS_NOT_FOUND, INVALID_PRODUCT_OPTIONS, NO_AVAILABLE_DELIVERY_METHODS, and the rest of the list on that operation. Authentication and scope failures follow the usual codes; see Making a REST Request. Every draft-orders endpoint requires a REST API token: a token issued for the GraphQL API receives a 403 with code REST_TOKEN_REQUIRED.

{
  "code": "PRODUCTS_NOT_FOUND",
  "message": "The following products were not found: not-a-real-sku"
}

Addressing a draft by id adds two more codes:

Status Code Meaning Where
404 DRAFT_ORDER_NOT_FOUND No draft order with this id is visible to the caller Fetching and placing
409 DRAFT_ORDER_ALREADY_PLACED This draft has already been placed; the message names the order it became Placing

An id that never existed and one belonging to another organization answer identically, so neither endpoint can be used to discover which draft ids exist.

{
  "code": "DRAFT_ORDER_ALREADY_PLACED",
  "message": "This draft order has already been placed as order SIBI-12345678"
}

Testing

The test environment serves the same endpoints under https://dev.sibi.pro/draft-orders*, so a draft is created with POST https://dev.sibi.pro/draft-orders, read back with GET https://dev.sibi.pro/draft-orders/{id}, and placed with POST https://dev.sibi.pro/draft-orders/{id}/order. Mint a test REST API token for it — a production token sent to the test host, or a test token sent to https://api.sibipro.com, is refused with 403 TOKEN_ENVIRONMENT_MISMATCH. Drafts priced there price against test data, and orders placed there trigger no real shipment or charge.

Endpoints

Draft Orders endpoints

Every endpoint with parameters, response schemas, and code samples.

Was this page helpful?