Developer Portal

Quickstart

Get your credentials, mint a token, and submit your first order. About ten minutes once you have access, entirely in the sandbox — nothing you do here reaches a real warehouse.

Step 1
Get your credentials

Credentials are issued by Kinimatic, not self-served. Tell us about your integration and we will send you a client id and secret scoped to what you need — ext:outbound:write and ext:outbound:read to start with, inbound permissions added later.

The client secret is shown to you once, when we issue it. Store it somewhere your application can read at run time; if it is lost we rotate rather than resend.

Request access
Step 2
Get an access token

Exchange your client id and secret for a bearer token. Tokens last one hour.

Cache the token for its full hour. Minting one per request is the most common integration mistake we see, and it will get you throttled — token minting is capped per account and shared with staff sign-in.
Step 3
Find a facility to ship from

Every order names the facility it ships from, by its facilityId. Call GET /facilities to fetch the ones you are assigned to. An order naming a facility you are not assigned to is refused with a 403.

Step 4
Submit an order

Post the order with your own reference. You get a 202 and an order id straight away — fulfilment continues in the background.

Do it against the sandbox first — a create there is free, and it is the same code path production runs, so a payload that works there works here.

Step 5
Watch it progress

Poll the order until it ships, or add a notification endpoint and we will post to you when it does. Most integrations do both: notifications for speed, polling as the safety net.

How webhooks work

What to build next

Handle the refusals

An accepted order is not a shipped order. Watch for order.refused and order.short_shipped — those are the ones a human needs to see.

Page by cursor, never by page number

Order lists change while you read them. Page numbers skip rows; cursors do not.

Respect 429

Back off for the number of seconds in Retry-After. Retrying immediately makes it worse.

Get a token
curl -X POST https://sandbox.api.kinimatic.com/oauth2/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=$KINIMATIC_CLIENT_ID" \
  -d "client_secret=$KINIMATIC_CLIENT_SECRET" \
  -d "scope=ext:outbound:write ext:outbound:read"

# → cache this for the full hour
{
  "access_token": "eyJhbGciOi…",
  "token_type": "Bearer",
  "expires_in": 3600
}
Then submit an order
curl -X POST "https://sandbox.api.kinimatic.com\
  /outbound/ext/v1/orders" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "orderNumber": "SO-000001",
    "facilityId": "019faa4e-4b53-…",
    "lines": [
      { "sku": "2116",
        "orderedQty": 480,
        "uom": "EA" }
    ]
  }'
202 Accepted171 ms
{
  "orderId": "019ffd80-2c41-…-b7a9e2f10c33",
  "orderNumber": "SO-000001"
}

Webhooks

We post a signed message to your endpoint when something happens to your orders. Verify the signature on every message, and expect repeats — we deliver at least once.

Not sure which events to subscribe to? The catalog lists every event we send, what it means, and which five actually need acting on.

How delivery works

Guarantee
At least once. A message can arrive more than once — key your handler on Kinimatic-Event-Id and make reprocessing a no-op.
Ordering
Not guaranteed. Two events about the same order can arrive out of sequence; trust the timestamps in the body over arrival order.
Retries
Any non-2xx, or no answer within 10 seconds, is retried with exponential backoff for 24 hours.
Pausing
After 12 consecutive failures we stop sending and tell you. Nothing is lost — when the endpoint is healthy again we redeliver everything from the pause.
Setup
Endpoints, event subscriptions and signing secrets are configured for you when your integration is provisioned. Contact us to add or change one.

Verifying a message

# Every message carries these headers
Kinimatic-Event-Id:   evt_019ffd66a1c4f2
Kinimatic-Signature:  t=1786709021,v1=8f3c…d41a
Kinimatic-Attempt:    1

# Sign the timestamp and the raw body with your secret,
# then compare with a constant-time equality check.
signature = hmac_sha256(secret, f"{timestamp}.{raw_body}")

# During rotation, accept EITHER active secret.
# Reject anything older than 5 minutes.