Developers
Buy from Big Sky Dynamics with code, not phone calls
A REST API for catalog, price, availability, quotes and orders, plus EDI for the transactions your ERP already speaks. These docs are public; keys and order endpoints need an account.
Overview
The partner API covers the whole buy path you would otherwise do by email: search the catalog, get your price and availability, create a quote, convert it to an order, then pull order status, EDI payloads and PDF documents.
Base URL: https://portal.bsdyno.com/api — the same host as this site,
same TLS certificate, no separate hostname to allowlist.
- Catalog, price and availability: read-only, safe to poll.
- Quotes: create and convert; quotes are valid 30 days.
- Orders: status, tracking, ASN and invoice/PO PDFs.
- EDI: 850 inbound, 855/856/810 outbound, 997 acknowledgements.
Authentication
Send your key in the X-API-Key header. Authorization: Bearer <key>
is accepted too.
curl -s https://portal.bsdyno.com/api/catalog?q=GPU&limit=1 \ -H "X-API-Key: $BSD_API_KEY"
- Keys are scoped per customer account, not per user — rotate them in the account area or by asking us.
- Create a second key before you retire the first so nothing breaks mid-rotation.
- Keys are never sent to a browser; the portal itself keeps them server-side.
- A request without a key, or with a wrong key, gets
401 auth_required.
Conventions
- JSON in, JSON out;
Content-Type: application/jsonon every POST. - Money appears twice:
unit_price_cents(integer, exact) andunit_price(decimal, display). Use the cents field for arithmetic. - Timestamps are ISO-8601 UTC.
- Ids are opaque strings (
Q-20261107-0005,O-20261107-0004,DOC-20261107-0007). Never parse them. - Errors are always
{"error": {"code": "...", "message": "..."}}.
Endpoints
| Method | Path | Auth | Purpose |
|---|---|---|---|
| GET | /health | none | Liveness and provider status. |
| GET | /catalog?q=&category=&vendor=&limit=&offset= | key | Search or page the catalog. |
| GET | /products/{id} | key | Specs, docs and live availability for one product. |
| GET | /price?sku=&qty=&channel= | key | Your price, all channels, quantity breaks. |
| GET | /availability?sku=&qty= | key | Stock, allocation and lead time. |
| POST | /quote | key | Create a quote; returns quote id, totals and expiry. |
| POST | /quote/{id}/convert | key | Convert an open quote into an order. |
| GET | /orders/{id} | key + buyer email | Status, tracking, ASN, line detail. |
| GET | /orders/{id}/edi855 | edi856 | edi810 | key + buyer email | Rendered X12 payload for that order. |
| POST | /documents/quote | key | Quotation PDF for a quote id. |
| POST | /documents/order/{id} | key + buyer email | Purchase order, packing slip and invoice PDFs. |
| GET | /documents/{doc_id}.pdf?v=<sha> | content token | Immutable issued document; the token is in your own link. |
| POST | /webhooks/edi850 | key | Inbound EDI 850 PO (JSON summary). |
| POST | /webhooks/edi/file | key | Inbound raw X12 file; returns the 997. |
Order and document lookups additionally require the
buyer email on the order (?email=). That is deliberate: order ids are sequential,
so a bare id must never be enough to read someone else’s order.
Pricing & contract rates
/price prices one SKU at one quantity with the same engine that writes your
quotes, and returns every channel:
{
"sku": "33P01IB0BB",
"quantity": 1,
"channel": "partner",
"unit_price_cents": 201399,
"channels": {
"list": { "unit_price_cents": 201399 },
"partner": { "unit_price_cents": 201399 },
"wholesale": { "unit_price_cents": 201399 },
"gov": { "unit_price_cents": 201399 },
"edu": { "unit_price_cents": 201399 }
},
"pricing_trail": [ ... ],
"as_of": "2026-11-08T13:35:38+00:00"
}
partneris your contract channel;listis the public price.- The portal price-list page shows both side by side and exports them as CSV.
- A special price authorization on your account overrides the channel price and applies automatically to quotes.
- Quantity breaks are priced per line: send the quantity you intend to buy.
Quotes → orders
curl -s -X POST https://portal.bsdyno.com/api/quote \
-H "X-API-Key: $BSD_API_KEY" -H "Content-Type: application/json" \
-d '{"items":[{"sku":"33P01IB0BB","qty":8}],"terms":"net30",
"customer":{"name":"Buyer","email":"[email protected]"}}'
curl -s -X POST https://portal.bsdyno.com/api/quote/Q-20261107-0005/convert \
-H "X-API-Key: $BSD_API_KEY" -H "Content-Type: application/json" \
-d '{"po_number":"PO-12345"}'
- Quotes are valid 30 days; an expired or already-converted quote returns
409. - Anonymous quote creation from the public site is rate limited; API key calls carry your account identity.
- The convert response is the order, including its
idfor later status and documents.
Orders & documents
curl -s "https://portal.bsdyno.com/api/orders/[email protected]" \ -H "X-API-Key: $BSD_API_KEY" curl -s -X POST "https://portal.bsdyno.com/api/documents/order/[email protected]" \ -H "X-API-Key: $BSD_API_KEY" -H "Content-Type: application/json" \ -d '{"kinds":["invoice"]}'
Document rendering is idempotent: calling it twice for the same order and kind returns the
same document id. Every issued document records a SHA-256 of both renditions, and the
?v= token in its URL is that hash prefix — so a link cannot be pointed at
another document.
EDI 850 / 855 / 856 / 810
X12 004010. Test and production are separated by the ISA usage indicator
(T / P); ISA/GS qualifiers and ids are issued to you at
onboarding.
| Set | Direction | Trigger | Key segments we emit |
|---|---|---|---|
| 850 | inbound | Your PO to us (raw X12 or JSON summary). | Parse + validate; ST*850, BEG, PO1, CTT. A 997 is returned. |
| 855 | outbound | We acknowledge your 850 per line. | BAK*00*AC*<po>, REF*AC, N1*ST, PO1 + ACK*IA per line, CTT. |
| 856 | outbound | Order ships. | BSN*00*<asn>, DTM*011, HL shipment/order/item, PRF*<po>, LIN*VP*<sku>*BP*<mpn>, SN1, CTT. |
| 810 | outbound | Order invoices. | BIG*<date>*<invoice>*<po date>*<po>, CUR*BY*USD, ITD*01*3****30, IT1 + PID per line, TDS, CTT. |
| 997 | both | Every accepted or rejected interchange. | Exactly one 997 per interchange (never for a 997), control numbers swapped. |
Also supported by the same registry: 846 (inventory
inquiry) and 832 (price/sales catalog). Envelope: ISA ·
GS · ST · SE · GE
· IEA. Transport: AS2 (signed, MDN) preferred, SFTP with PGP on request.
Test payloads before production — we will send you a test 850 and confirm the 997.
Errors & limits
| Status | Code | What to do |
|---|---|---|
| 401 | auth_required | Send a valid X-API-Key; for order/document calls also send the buyer email. |
| 403 | forbidden | Your key is valid but lacks the role for that action. |
| 404 | not_found | Unknown SKU, order or document. Order lookups never reveal whether an id exists for another buyer. |
| 409 | conflict | Quote expired or already converted — create a new quote. |
| 422 | invalid_request | Validation failed; read the details object for the field. |
| 429 | rate_limited | Back off using the Retry-After header, then retry with jitter. |
| 502 | upstream | Our side failed. Retry once, then contact us with the timestamp. |
- Anonymous quote creation: 3 per 5 minutes and 10 per hour per client IP.
- Catalog, price and availability: poll no faster than once per second per key.
- Document generation is idempotent and cached — safe to retry.
Go-live checklist
- Send us your use case (quote automation, price sync, drop-ship, EDI).
- We provision your account, contract price list and API key.
- If EDI: we agree ISA/GS ids, transport (AS2 or SFTP) and test vs production.
- Run a test quote, convert it to a test order and pull the invoice PDF in our sandbox.
- Exchange one test 850 → 855 and one 856, and confirm the 997 in both directions.
- Go live; we watch the first 48 hours with you.