API Reference

PB&J Platform API

Reference for orders, customers, and inventory endpoints. Includes enum values, request schemas, and error responses.

Base information v1 (stable)
Base URL
https://api.pbandj.io/v1
Authentication
X-API-Key header
Rate limit
120 requests/minute

Overview

Every order is tied to a customer_id and returns a unique order_id that you use for follow-up GET, PUT, and DELETE requests. Orders reserve inventory and release it when canceled.

  • Send X-API-Key with every request.
  • Use customer_id to track the customer and order_id to track the order.
  • Order statuses: queued, prepping, toasting, ready, delivered, canceled.

Enum values

Bread

sourdough brioche whole_wheat rye

Peanut butter

smooth chunky honey_roast

Jelly

strawberry grape raspberry apricot

Toast and cut options

toast: light toast: golden toast: dark cut: diagonal cut: halves cut: triangles
POST /orders

Create an order for a customer. The API reserves inventory and returns an order_id you can use to check status.

Query parameters

None.

Body parameters

Field Type Description Allowed values
customer_id * string Customer identifier for order history and reorders.
bread * string Bread choice for the sandwich. sourdough, brioche, whole_wheat, rye
peanut_butter * string Peanut butter style for the order. smooth, chunky, honey_roast
jelly * string Jelly flavor for the order. strawberry, grape, raspberry, apricot
toast string Toast level for the sandwich. light, golden, dark
cut string Cut style for the sandwich. diagonal, halves, triangles
notes string Free-form instructions for the prep line.
extras array Optional add-ons for the order. banana_slices, marshmallow_fluff, honey_drizzle

Response schema

Field Type Description Allowed values
order_id string Unique order identifier.
customer_id string Customer identifier for the order.
status string Current order status. queued, prepping, toasting, ready, delivered, canceled
eta_minutes number Estimated minutes until ready.
choices object Selections for the order.
choices.bread string Bread selection. sourdough, brioche, whole_wheat, rye
choices.peanut_butter string Peanut butter selection. smooth, chunky, honey_roast
choices.jelly string Jelly selection. strawberry, grape, raspberry, apricot
choices.toast string Toast selection. light, golden, dark
choices.cut string Cut selection. diagonal, halves, triangles
choices.extras array Optional add-ons for the order. banana_slices, marshmallow_fluff, honey_drizzle

Requests

curl -X POST https://api.pbandj.io/v1/orders \
  -H "Content-Type: application/json" \
  -H "X-API-Key: pbj_test_8dd1f2" \
  -d '{
    "customer_id": "cus_2048",
    "bread": "brioche",
    "peanut_butter": "smooth",
    "jelly": "raspberry",
    "toast": "light",
    "cut": "triangles",
    "extras": ["banana_slices"]
  }'
const response = await fetch('https://api.pbandj.io/v1/orders', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-API-Key': 'pbj_test_8dd1f2',
  },
  body: JSON.stringify({
    customer_id: 'cus_2048',
    bread: 'brioche',
    peanut_butter: 'smooth',
    jelly: 'raspberry',
    toast: 'light',
    cut: 'triangles',
    extras: ['banana_slices'],
  }),
});

const data = await response.json();
console.log(data);
import requests

response = requests.post(
    "https://api.pbandj.io/v1/orders",
    headers={"X-API-Key": "pbj_test_8dd1f2"},
    json={
        "customer_id": "cus_2048",
        "bread": "brioche",
        "peanut_butter": "smooth",
        "jelly": "raspberry",
        "toast": "light",
        "cut": "triangles",
        "extras": ["banana_slices"],
    },
)

print(response.json())

Responses

{
  "order_id": "ord_41b7",
  "customer_id": "cus_2048",
  "status": "prepping",
  "eta_minutes": 5,
  "choices": {
    "bread": "brioche",
    "peanut_butter": "smooth",
    "jelly": "raspberry",
    "toast": "light",
    "cut": "triangles",
    "extras": ["banana_slices"]
  }
}
{
  "error": "invalid_enum",
  "message": "Value 'blueberry' is not a valid jelly option.",
  "field": "jelly",
  "allowed": ["strawberry", "grape", "raspberry", "apricot"]
}
{
  "error": "out_of_stock",
  "message": "Strawberry jelly is out of stock.",
  "item": {
    "type": "jelly",
    "option": "strawberry"
  },
  "suggested": ["grape", "raspberry"]
}
GET /orders/{order_id}

Retrieve an order by order_id.

Path parameters

Name Type Description Allowed values
order_id * string Unique order identifier.

Query parameters

None.

Body parameters

None.

Response schema

Field Type Description Allowed values
order_id string Unique order identifier.
customer_id string Customer identifier for the order.
status string Current order status. queued, prepping, toasting, ready, delivered, canceled
eta_minutes number Estimated minutes until ready.
choices object Selections for the order.
choices.bread string Bread selection. sourdough, brioche, whole_wheat, rye
choices.peanut_butter string Peanut butter selection. smooth, chunky, honey_roast
choices.jelly string Jelly selection. strawberry, grape, raspberry, apricot
choices.toast string Toast selection. light, golden, dark
choices.cut string Cut selection. diagonal, halves, triangles
choices.extras array Optional add-ons for the order. banana_slices, marshmallow_fluff, honey_drizzle

Requests

Request body: none.

curl https://api.pbandj.io/v1/orders/ord_41b7 \
  -H "X-API-Key: pbj_test_8dd1f2"
const response = await fetch('https://api.pbandj.io/v1/orders/ord_41b7', {
  headers: {
    'X-API-Key': 'pbj_test_8dd1f2',
  },
});

const data = await response.json();
console.log(data);
import requests

response = requests.get(
    "https://api.pbandj.io/v1/orders/ord_41b7",
    headers={"X-API-Key": "pbj_test_8dd1f2"},
)

print(response.json())

Responses

{
  "order_id": "ord_41b7",
  "customer_id": "cus_2048",
  "status": "toasting",
  "eta_minutes": 3,
  "choices": {
    "bread": "brioche",
    "peanut_butter": "smooth",
    "jelly": "raspberry",
    "toast": "light",
    "cut": "triangles",
    "extras": ["banana_slices"]
  }
}
{
  "error": "order_not_found",
  "message": "No order exists for order_id ord_9001."
}
{
  "error": "unauthorized",
  "message": "The X-API-Key header is missing or invalid."
}
PUT /orders/{order_id}

Update toast, cut, or notes while the order is queued or prepping.

You can update orders only when the status is queued or prepping.

Path parameters

Name Type Description Allowed values
order_id * string Unique order identifier.

Query parameters

None.

Body parameters

Field Type Description Allowed values
toast string New toast level. light, golden, dark
cut string New cut style. diagonal, halves, triangles
notes string Additional prep instructions for the grill.

Response schema

Field Type Description Allowed values
order_id string Unique order identifier.
status string Current order status. queued, prepping, toasting, ready, delivered, canceled
toast string Updated toast level. light, golden, dark
cut string Updated cut style. diagonal, halves, triangles
notes string Updated prep instructions.
updated_at string ISO 8601 timestamp of the update.

Requests

curl -X PUT https://api.pbandj.io/v1/orders/ord_41b7 \
  -H "Content-Type: application/json" \
  -H "X-API-Key: pbj_test_8dd1f2" \
  -d '{
    "toast": "dark",
    "notes": "Cut corner for easy carry"
  }'
const response = await fetch('https://api.pbandj.io/v1/orders/ord_41b7', {
  method: 'PUT',
  headers: {
    'Content-Type': 'application/json',
    'X-API-Key': 'pbj_test_8dd1f2',
  },
  body: JSON.stringify({
    toast: 'dark',
    notes: 'Cut corner for easy carry',
  }),
});

const data = await response.json();
console.log(data);
import requests

response = requests.put(
    "https://api.pbandj.io/v1/orders/ord_41b7",
    headers={"X-API-Key": "pbj_test_8dd1f2"},
    json={
        "toast": "dark",
        "notes": "Cut corner for easy carry",
    },
)

print(response.json())

Responses

{
  "order_id": "ord_41b7",
  "status": "prepping",
  "toast": "dark",
  "cut": "triangles",
  "notes": "Cut corner for easy carry",
  "updated_at": "2026-03-15T10:21:12Z"
}
{
  "error": "invalid_enum",
  "message": "Toast must be one of: light, golden, dark.",
  "field": "toast"
}
{
  "error": "invalid_status",
  "message": "Orders can be updated only when the status is queued or prepping.",
  "status": "toasting"
}
DELETE /orders/{order_id}

Cancel an order and release reserved inventory.

You can cancel orders only when the status is queued or prepping.

Path parameters

Name Type Description Allowed values
order_id * string Unique order identifier.

Query parameters

None.

Body parameters

None.

Response schema

Field Type Description Allowed values
order_id string Unique order identifier.
status string Order status after cancellation. canceled

Requests

Request body: none.

curl -X DELETE https://api.pbandj.io/v1/orders/ord_41b7 \
  -H "X-API-Key: pbj_test_8dd1f2"
const response = await fetch('https://api.pbandj.io/v1/orders/ord_41b7', {
  method: 'DELETE',
  headers: {
    'X-API-Key': 'pbj_test_8dd1f2',
  },
});

const data = await response.json();
console.log(data);
import requests

response = requests.delete(
    "https://api.pbandj.io/v1/orders/ord_41b7",
    headers={"X-API-Key": "pbj_test_8dd1f2"},
)

print(response.json())

Responses

{
  "order_id": "ord_41b7",
  "status": "canceled"
}
{
  "error": "order_not_found",
  "message": "No order exists for order_id ord_9999."
}
{
  "error": "invalid_status",
  "message": "Orders can be canceled only when the status is queued or prepping.",
  "status": "toasting"
}
POST /customers

Create a customer profile and return a customer_id for future orders.

Query parameters

None.

Body parameters

Field Type Description Allowed values
name * string Customer display name.
email * string Email address for notifications and receipts. Valid email format
favorite_bread string Preferred bread choice. sourdough, brioche, whole_wheat, rye
favorite_jelly string Preferred jelly flavor. strawberry, grape, raspberry, apricot

Response schema

Field Type Description Allowed values
customer_id string Unique customer identifier.
name string Customer display name.
email string Email address on file.
favorite_bread string Preferred bread choice. sourdough, brioche, whole_wheat, rye
favorite_jelly string Preferred jelly flavor. strawberry, grape, raspberry, apricot

Requests

curl -X POST https://api.pbandj.io/v1/customers \
  -H "Content-Type: application/json" \
  -H "X-API-Key: pbj_test_8dd1f2" \
  -d '{
    "name": "Avery Simmons",
    "email": "avery@diner.dev",
    "favorite_bread": "sourdough",
    "favorite_jelly": "strawberry"
  }'
const response = await fetch('https://api.pbandj.io/v1/customers', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-API-Key': 'pbj_test_8dd1f2',
  },
  body: JSON.stringify({
    name: 'Avery Simmons',
    email: 'avery@diner.dev',
    favorite_bread: 'sourdough',
    favorite_jelly: 'strawberry',
  }),
});

const data = await response.json();
console.log(data);
import requests

response = requests.post(
    "https://api.pbandj.io/v1/customers",
    headers={"X-API-Key": "pbj_test_8dd1f2"},
    json={
        "name": "Avery Simmons",
        "email": "avery@diner.dev",
        "favorite_bread": "sourdough",
        "favorite_jelly": "strawberry",
    },
)

print(response.json())

Responses

{
  "customer_id": "cus_2048",
  "name": "Avery Simmons",
  "email": "avery@diner.dev",
  "favorite_bread": "sourdough",
  "favorite_jelly": "strawberry"
}
{
  "error": "invalid_email",
  "message": "Email address must be valid.",
  "field": "email"
}
GET /customers/{customer_id}/orders

List recent orders for a customer by customer_id.

Path parameters

Name Type Description Allowed values
customer_id * string Customer identifier for the order list.

Query parameters

Name Type Description Allowed values
status string Filter orders by status. queued, prepping, toasting, ready, delivered, canceled
limit number Maximum number of orders to return. 1-100

Body parameters

None.

Response schema

Field Type Description Allowed values
customer_id string Customer identifier for the list.
orders array Orders for the customer.
orders[].order_id string Order identifier.
orders[].status string Order status. queued, prepping, toasting, ready, delivered, canceled

Requests

Request body: none.

curl "https://api.pbandj.io/v1/customers/cus_2048/orders?status=ready&limit=5" \
  -H "X-API-Key: pbj_test_8dd1f2"
const response = await fetch(
  'https://api.pbandj.io/v1/customers/cus_2048/orders?status=ready&limit=5',
  {
    headers: {
      'X-API-Key': 'pbj_test_8dd1f2',
    },
  }
);

const data = await response.json();
console.log(data);
import requests

response = requests.get(
    "https://api.pbandj.io/v1/customers/cus_2048/orders",
    headers={"X-API-Key": "pbj_test_8dd1f2"},
    params={"status": "ready", "limit": 5},
)

print(response.json())

Responses

{
  "customer_id": "cus_2048",
  "orders": [
    { "order_id": "ord_41b7", "status": "ready" },
    { "order_id": "ord_41a2", "status": "delivered" }
  ]
}
{
  "error": "unauthorized",
  "message": "The X-API-Key header is missing or invalid."
}
GET /inventory

Check current stock for menu options.

Query parameters

None.

Body parameters

None.

Response schema

Field Type Description Allowed values
updated_at string ISO 8601 timestamp of the inventory snapshot.
items array Inventory items by category and option.
items[].type string Item category. bread, peanut_butter, jelly
items[].option string Menu option name.
items[].available number Units available for new orders.
items[].reserved number Units held by active orders.
items[].status string Stock state. in_stock, low, out_of_stock

Requests

Request body: none.

curl https://api.pbandj.io/v1/inventory \
  -H "X-API-Key: pbj_test_8dd1f2"
const response = await fetch('https://api.pbandj.io/v1/inventory', {
  headers: {
    'X-API-Key': 'pbj_test_8dd1f2',
  },
});

const data = await response.json();
console.log(data);
import requests

response = requests.get(
    "https://api.pbandj.io/v1/inventory",
    headers={"X-API-Key": "pbj_test_8dd1f2"},
)

print(response.json())

Responses

{
  "updated_at": "2026-03-15T10:12:00Z",
  "items": [
    {
      "type": "bread",
      "option": "sourdough",
      "available": 14,
      "reserved": 2,
      "status": "in_stock"
    },
    {
      "type": "jelly",
      "option": "strawberry",
      "available": 0,
      "reserved": 1,
      "status": "out_of_stock"
    }
  ]
}
{
  "error": "unauthorized",
  "message": "The X-API-Key header is missing or invalid."
}

Errors

Response schema

Field Type Description Allowed values
error string Machine-readable error code. invalid_enum, invalid_email, unauthorized, order_not_found, out_of_stock, rate_limited, invalid_status
message string Human-readable error message.
field string Field name that caused the error when applicable.
allowed array Allowed values for the field when applicable.
item object Item details for inventory-related errors.
status string Current order status for invalid status errors. queued, prepping, toasting, ready, delivered, canceled
Status Code Message
400 invalid_enum Selected value is not allowed for this field.
400 invalid_email Email address must be valid.
401 unauthorized API key is missing or invalid.
404 order_not_found No order exists for that order_id.
409 out_of_stock Requested item is out of stock.
409 invalid_status Order status does not allow this action.
429 rate_limited Retry after the reset time.
Out of stock response
{
  "error": "out_of_stock",
  "message": "Strawberry jelly is out of stock.",
  "item": {
    "type": "jelly",
    "option": "strawberry"
  }
}