BoardBid API v1
The BoardBid API is the pricing infrastructure layer for the corrugated packaging industry. This reference documents every public endpoint, schema, and operational detail you need to integrate.
Base URL: https://boardbid.io/api (routed to Supabase Edge Functions)
Current version: v1.0.0 · Stable
Auth: Bearer token in Authorization header
Content type: application/json for all POST bodies
Introduction
BoardBid turns natural-language corrugated packaging quote requests into structured, priced, trackable offers. The API has three core endpoints:
POST /v1/parse-quote— converts free-form text into a ParsedQuote objectPOST /v1/price-quote— converts a ParsedQuote into a priced offer (beta)GET /v1/health— service health check
The same API powers the BoardBid web app (boardbid.io/app), the mobile experience, and any partner integration. There is no private or "premium" API path — what the web app can do, you can do.
Quick start
The fastest way to see what the API returns is to call it. Get an API key from boardbid.io/app (free tier includes 500 parse calls per month), then:
curl -X POST https://boardbid.io/api/v1/parse-quote \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "x-boardbid-client: my-app-v1" \
-d '{"text": "RSC 15x10x5 32ECT 871 qty for QEP"}'
Expected response:
{
"api_version": "1.0.0",
"request_id": "req_lxyz123_abc",
"parse": {
"type": "RSC",
"length": 15,
"width": 10,
"depth": 5,
"ect": 32,
"wall": null,
"quantity": 871,
"customer": "QEP",
"joint": null
},
"confidence": 0.98,
"notes": null,
"trace": {
"model": "claude-sonnet-4-5",
"latency_ms": 823,
"claude_ms": 810,
"regex_agreement": {
"fields_regex_matched": 7,
"fields_agreed": 7,
"disagreements": []
},
"input_tokens": 320,
"output_tokens": 85
}
}
Authentication
Every request must include a Bearer token in the Authorization header:
Authorization: Bearer YOUR_API_KEY
API keys are issued from your BoardBid account. Each key:
- Is scoped to a single tenant (your organization)
- Can be rotated at any time without downtime (multiple active keys per tenant)
- Inherits tenant-level permissions via row-level security on the backend database
- Is logged on every request for audit purposes
Never put a service role key in client-side code. Service role keys bypass row-level security and should only ever be used in server-side integrations. Use the standard API key (anon JWT) for browser and mobile clients.
Client identification
Include the x-boardbid-client header to identify your integration in logs and analytics:
x-boardbid-client: acme-erp-v2
Recommended format: <product>-<environment>-<major-version>. This header is not used for authorization, only for observability. It appears in the client column of our request logs, which makes support conversations faster.
Versioning
BoardBid uses URL path versioning: /v1/parse-quote, /v1/price-quote, etc. The current stable version is v1.0.0.
What counts as a breaking change
We bump the major version (to /v2/) when any of the following change:
- A required response field is renamed, removed, or has its type changed
- Required request fields are added
- An existing error code changes meaning
- The semantic meaning of a field value changes
Non-breaking changes
These we ship without a version bump:
- Adding optional request fields
- Adding new response fields
- Adding new error codes (always parse errors defensively — unknown codes may appear)
- Adding new enum values (strict parsers beware)
- Improving parse accuracy (outputs improve, schema is identical)
Deprecation policy
When v2 ships:
- v1 continues to serve for at least 12 months
DeprecationandSunsetHTTP headers are added to v1 responses per RFC 8594- Email notice is sent to every API key that used v1 in the preceding 30 days
- A migration guide is published at
/docs/migrations/v1-to-v2
Request IDs
Every response includes a request_id in both the response body and the x-boardbid-request-id header. Keep this ID with every log you write about an API call — it unlocks support.
x-boardbid-request-id: req_lxyz123_abc
x-boardbid-version: 1.0.0
When filing a support issue, include the request ID. We can look up the full server-side trace of that specific call — input, output, latency, model version, which internal code path ran.
POST /v1/parse-quote
Converts free-form quote request text into a ParsedQuote object.
Request
POST /v1/parse-quote
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
x-boardbid-client: your-app-v1
{
"text": "RSC 15x10x5 32ECT 871 qty for QEP",
"client": "optional-client-override",
"hints": {
"known_customers": ["QEP", "Henderson", "CPS"],
"default_type": "RSC"
}
}
Parameters
| Field | Type | Required | Description |
|---|---|---|---|
text | string (1–2000 chars) | Yes | The quote request to parse. Accepts industry shorthand, natural language, or mixed. |
client | string | No | Client identifier for logs. Falls back to x-boardbid-client header. |
hints.known_customers | string[] | No | Known customer names or aliases. Improves customer extraction when context is ambiguous. |
hints.default_type | BoxType | No | Default box type if the parser cannot determine one. See enums. |
Response
Returns 200 OK with a ParsedQuote response body on success. See schema below.
Example
{
"api_version": "1.0.0",
"request_id": "req_lxyz123_abc",
"parse": {
"type": "RSC",
"length": 15, "width": 10, "depth": 5,
"ect": 32, "wall": null,
"quantity": 871,
"customer": "QEP",
"joint": null
},
"confidence": 0.98,
"notes": null,
"trace": { /* see ParseTrace */ }
}
POST /v1/price-quote Beta
Converts a ParsedQuote into a priced offer. Currently returns 501 Not Implemented with the response schema fully defined — this lets you integrate against the contract today and switch to live pricing when it ships.
Request
POST /v1/price-quote
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
{
"quote": {
"type": "RSC",
"length": 15, "width": 10, "depth": 5,
"ect": 32, "quantity": 871,
"customer": "QEP", "joint": "GLUED", "wall": null
},
"plant_id": "optional-plant-uuid",
"hints": {
"target_margin_pct": 25,
"markup_pct": 15
}
}
Response shape (when live)
{
"api_version": "1.0.0",
"request_id": "req_...",
"price_per_piece": 0.4672,
"total_price": 407.15,
"breakdown": {
"sheet_width": 11.625,
"sheet_length": 52.25,
"msf": 5.264,
"board_cost": 184.22,
"process_cost": 73.40,
"ink_cost": 0.00,
"tooling_amortized": 0.00,
"indirect_cost": 51.90,
"total_cogs": 309.52,
"markup_applied_pct": 15,
"margin_pct": 24.8
},
"trace": {
"plant_id": "plant_abc123",
"pricing_model_version": "v1",
"latency_ms": 42
}
}
GET /v1/health
Service health check. Use for uptime monitoring.
curl https://boardbid.io/api/v1/health
# No auth required
{
"api_version": "1.0.0",
"status": "ok",
"services": {
"claude": "ok",
"database": "ok"
},
"timestamp": "2026-04-16T14:30:00.000Z"
}
Returns 200 when all services are healthy, 503 otherwise.
ParsedQuote schema
This is the central data structure. Every parse endpoint returns one; the price endpoint accepts one.
| Field | Type | Description |
|---|---|---|
type | BoxType or null | Box style. See enums. |
length | number or null | Inside dimension length in inches. |
width | number or null | Inside dimension width in inches. |
depth | number or null | Inside dimension depth in inches. |
ect | integer or null | Edge Crush Test rating. Typical: 32, 40, 44, 48, 51, 55, 61, 71. |
wall | WallGrade or null | Wall construction. See enums. |
quantity | integer or null | Order quantity in pieces. |
customer | string or null | Customer or account name. |
joint | JointType or null | How the box is assembled. |
Enums
BoxType
| Value | Meaning |
|---|---|
"RSC" | Regular Slotted Container — the most common corrugated box style. |
"HSC" | Half Slotted Container. |
"FOL" | Full Overlap container. |
"DC RSC" | Die-cut RSC — RSC with custom die-cut features. |
"DC HSC" | Die-cut HSC. |
"DC" | Die-cut box (generic). |
"TUBE" | Tube or sleeve-style box. |
"TRAY" | Tray or bliss-style. |
"5PF" | 5-panel folder. |
WallGrade
"SW"— single wall (most common)"DW"— double wall (heavy duty)"TW"— triple/twin wall (industrial)
JointType
"GLUED"— glued manufacturer's joint (most common)"STITCHED"— stitched"HOTMELT"— hot-melt adhesive
Error schema
Every error response follows a consistent shape:
{
"api_version": "1.0.0",
"error": {
"code": "invalid_input",
"message": "Field 'text' is required and must be a non-empty string",
"request_id": "req_lxyz123_abc",
"details": { /* optional, endpoint-specific */ }
}
}
Error handling
HTTP status codes follow REST conventions:
| Status | Error code | Meaning |
|---|---|---|
400 | invalid_json | Request body is not valid JSON. |
400 | invalid_input | Required field missing or wrong type. |
400 | input_too_long | Input exceeds the 2000-character limit. |
401 | — | Missing or invalid Authorization header. |
403 | — | Authenticated, but not authorized for this resource. |
405 | method_not_allowed | Wrong HTTP method (use POST for most endpoints). |
429 | — | Rate limit exceeded. |
500 | configuration_error | Server misconfiguration. Rare. Contact support with request_id. |
501 | not_implemented | Endpoint stub — implementation pending (price-quote). |
502 | upstream_error | Upstream model service failed or returned invalid output. |
Best practice: Parse error codes defensively. Always check the HTTP status first, then read the error code. Treat unknown codes as generic errors — we may add new codes without a major version bump.
Rate limits
Rate limits are per API key per minute:
| Tier | parse-quote | price-quote | health |
|---|---|---|---|
| Free | 30/min | 30/min | unlimited |
| Pro | 300/min | 300/min | unlimited |
| Enterprise | Custom | Custom | unlimited |
Rate-limited requests return 429 Too Many Requests with a Retry-After header. Exponential backoff with jitter is recommended.
Observability
Every request is logged server-side with:
- Request ID, client identifier, input text
- Full parsed output
- Confidence score and any notes
- Latency breakdown (total and upstream model)
- Model version
- Regex-validator agreement metrics
- Input and output token counts
Logs are retained indefinitely by default. Each tenant can query their own logs via authenticated database access. Cross-tenant access is prevented by row-level security.
Glossary
Terms we use throughout the docs.
Sheet plant
A corrugated box manufacturer. Typically regional, 20–200 employees. "Sheet" refers to corrugated sheets (the pre-cut raw material sheet plants convert into finished boxes).
ECT (Edge Crush Test)
The industry-standard test for corrugated board strength. A higher ECT number means a stronger board. Common values: 32 (standard shippers), 44 (heavier), 48–71 (industrial/heavy duty).
MSF (Thousand Square Feet)
The core pricing unit for corrugated board material. Board cost is quoted per MSF, with prices varying by ECT rating, flute type, and volume tier.
RSC / HSC / FOL
Box style abbreviations. RSC (Regular Slotted Container) is the most common — a standard shipping box with flaps that meet in the middle. HSC (Half Slotted) has flaps on only one side, typically used as inserts or trays. FOL (Full Overlap) has overlapping flaps for extra strength.
Flute
The wavy corrugated medium between liners. Common flute types: C (standard), B (finer, for print), BC (double wall B + C), TW (triple wall). Affects both strength and sheet-sizing math.
Joint
How the box is assembled into its final form. Glued joints use adhesive, stitched joints use metal staples, hot-melt uses heat-activated adhesive.
Die-cut (DC)
A box with custom-cut features beyond standard slots — hand holes, tabs, windows, complex shapes. Requires a dedicated cutting die (tool), which has its own cost that's typically amortized over the order quantity.
Documentation last updated 2026-04-16. Version 1.0.0. Report issues to hello@boardbid.io.