Orders
Manage orders across your shops. You can create orders directly or using GTINs (see Finding GTINs).
Location-routed orders
A franchise location does not own the network storefront. Orders placed on that storefront and routed to the location still show up on the location's API key.
getOrders with no shopId returns those orders, newest first. getOrder returns the line items. The same key cannot update a routed order; edits stay with the shop that took the payment.
query {
getOrders(limit: 20) {
id
orderNumber
customerEmail
dueDate { _seconds _nanoseconds }
fulfillment
grandTotal
shippingCost
totalTax
totalPrice
payout {
stripeFee
riverrFee
netPaid
currency
payoutId
arrivalDate
amount
transferId
}
orderItems {
id
name
quantity
price
mockups { url name placement }
printFiles { url name placement }
}
}
}
| Field | Description |
|---|---|
payout | Null until the customer's card payment has been split. Read the order again if a brand-new order has no payout yet. |
payout.stripeFee | Card processing fee withheld on this order, in dollars. |
payout.riverrFee | Riverr fee withheld on this order, in dollars. Shipping and tax are not charged this fee. |
payout.netPaid | Amount transferred to this account for the order. Product, shipping, and tax shares are already included, and the two fees above are already subtracted. Sum netPaid across the orders in one bank deposit to match the deposit. |
payout.payoutId | Stripe payout id (po_…) of the bank deposit this order settled into. Null until Stripe pays that deposit. |
payout.arrivalDate | Date that deposit lands in the bank, YYYY-MM-DD. |
payout.amount | Total dollars of that bank deposit. Repeated on every order in the deposit. Sum netPaid to reconcile the deposit. |
payout.transferId | Stripe transfer id (tr_…) for this order's share. Present once the split has been transferred, even if the deposit has not landed yet. |
orderItems.mockups | Customer-facing mockup URLs. |
orderItems.printFiles | Production file URLs. A line with an uploaded print file or DST uses that. Storefront lines use the print PNG the customizer exported at checkout. Preview images stay on images. |
customerEmail | Customer email, the same address as the order email. |
dueDate | Production due date. The order email prints this as a calendar date. |
fulfillment | pickup or shipping. Same split as the order email. |
orderItems.images | Preview and artwork images stored on the line. |
Subscribe to order.created to hear about a routed order as soon as it is assigned to the location. The webhook body is the order id. Fetch this query for items, files, and fees. See Webhooks.
Get Orders
Retrieve orders with optional filters. Shop filters still apply to shops this key owns. Omit shopId to include orders routed to your location.
query {
getOrders(shopId: "shop_123", shipped: false, limit: 10) {
id
orderNumber
shopId
shipped
cancelled
grandTotal
shippingCost
createdAt {
_seconds
_nanoseconds
}
shippingAddress {
name
address1
city
country
}
}
}
Filter Parameters
| Parameter | Type | Description |
|---|---|---|
shopId | ID | Filter by shop |
shipped | Boolean | Filter by shipped status |
cancelled | Boolean | Filter by cancelled status |
createdAfter | TimestampInput | Orders created after this time. Pass { _seconds, _nanoseconds }. |
updatedAfter | TimestampInput | Orders updated after this time. Pass { _seconds, _nanoseconds }. Do not combine with createdAfter. |
platformOrderId | String | Shopify order id (order.id). Returns that order directly. |
orderNumber | String | Shopify numeric order number, without the #. |
limit | Int | Max number of results |
Look up one order with platformOrderId or orderNumber and shopId. Leave the date filters off for that call. getOrder is only the Riverr order id.
Get a Single Order
getOrder now returns the full orderItems collection (previously the array came back empty).
You can also request per-item and per-order cost breakdowns and ShipStation shipping options.
query {
getOrder(id: "order_123") {
id
orderNumber
shipped
cancelled
grandTotal
shippingOptions {
carrierCode
serviceCode
packageCode
}
shippingLabel {
url
carrierName
carrierService
trackingCode
}
cost {
printingCost
fulfillmentCost
shippingCost
discount
totalCost
customerPaid
profit
estimated
currency
}
orderItems {
id
name
price
quantity
images {
url
placement
type
}
cost {
printingCost
fulfillmentCost
totalCost
currency
}
}
}
}
Per-item and per-order cost
OrderItem.cost and Order.cost are computed on-demand only when selected — they trigger
extra Firestore reads, so request them only when needed.
| Field | Description |
|---|---|
printingCost | Decoration / print cost from the enterprise pricing table for the item's decorationMethod (DTG, DTF, …), falling back to per-placement overlay prices when no table is attached |
fulfillmentCost | Blank product / PO unit cost × quantity, including supplier upcharge |
shippingCost | Resolved from blank product shippingPriceId and the destination country (Order-level only). null when not calculable. |
discount | Tier discount applied to printing cost (Order-level only) |
totalCost | printingCost + fulfillmentCost + shippingCost − discount |
customerPaid | Order.grandTotal (Order-level only) |
profit | customerPaid − totalCost (Order-level only) |
estimated | true until the order has been invoiced (Order-level only) |
currency | Order currency, defaults to USD |
Order status & tracking
Order exposes a derived lifecycle status, fine-grained tags, and inline
shipments so you can poll fulfillment without inspecting individual flags.
query {
getOrder(id: "order_123") {
status
statusTags
shipped
cancelled
shipments {
trackingCode
trackingUrl
carrierName
shippedAt { _seconds _nanoseconds }
}
}
}
| Field | Description |
|---|---|
status | Coarse, normalized status derived server-side: "production" | "unsynced" | "shipped" | "cancelled". Mirrors Riverr's internal search-index normalization. Precedence (last match wins): cancelled > shipped > unsynced (not fully mapped) > production. Eventually consistent — a brand-new order reads "production" until the mapping pipeline runs. |
statusTags | Finer pipeline tags (e.g. "pre-production", "in-production", "routed", "partially-shipped", "shipped", "draft"). Typed as a list for forward-compatibility; internal-only tags are filtered out. Empty until the pipeline has run. Treat as "current state", not history. |
shipments | All shipments for the order (every parcel). See Tracking & Fulfillment. |
Quote an order from GTIN
quoteOrderFromGtin prices a job against the same enterprise decoration
tables used for invoicing — without creating an order. Use it to pull DTG
vs DTF (or any other method) print rates, blank cost, and optional shipping
before you call createOrderFromGtin.
getBlankProducts does not return print prices. Order.cost after create
also reads these tables now, but a quote is the right call when you need the
number first.
| Field | Description |
|---|---|
printingCost | Decoration table rate × quantity |
fulfillmentCost | Blank / PO unit cost × quantity, including supplier upcharge |
shippingCost | From the blank's shipping table when shippingAddress.country or countryCode is set. Otherwise null. |
discount | Seller tier discount on printing, if any |
totalCost | printingCost + fulfillmentCost + shippingCost − discount |
items[].warnings | Method not on the product, unknown placement, or defaulted Front |
decorationMethod ids come from getDecorationMethods ("1" DTG, "6" DTF,
"3" embroidery, …). Placement ids come from
getPlacements ("1" Front, "2" Back, "3" Left Chest).
If you send a method the product does not offer — for example DTF "6"
on a DTG-only blank — and the printer uses pricing tables, the query fails.
We do not return $0 print and we do not silently substitute another method.
{
"errors": [
{
"message": "Not available — Please contact admin to add this decoration method for this product.",
"path": ["quoteOrderFromGtin"],
"extensions": { "code": "400" }
}
]
}
createOrderFromGtin rejects the same way if you send that method on the line.
Use a catalog GTIN that offers the method, or ask the printer admin to attach
it on the base product.
Enterprises that turn pricing tables off (Settings → Pricing tables) still
quote from per-placement overlay prices. $0 print is allowed there — that is
how shops like Candle Builders price.
When placements is omitted we quote Front ("1") and say so in warnings.
query QuoteOrderFromGtin($input: OrderQuoteFromGtinInput!) {
quoteOrderFromGtin(input: $input) {
printingCost
fulfillmentCost
shippingCost
discount
totalCost
currency
items {
gtin
name
style
color
size
quantity
decorationMethod
printingCost
fulfillmentCost
totalCost
placements {
placement
printingCost
}
warnings
}
}
}
{
"input": {
"shippingAddress": {
"country": "US"
},
"orderItems": [
{
"gtin": "00123456789012",
"quantity": 1,
"decorationMethod": "6",
"placements": ["1"]
}
]
}
}
Compare DTG vs DTF by calling the query twice with "1" and "6" on the
same GTIN — or on the DTG and DTF catalog GTINs if the printer split them
into separate products.
Create an Order
createOrder and createOrderFromGtin now both return the full orderItems
in the mutation response (previously they came back as an empty array).
You can optionally pass shippingOptions with ShipStation-aware fields
(carrierCode, serviceCode, packageCode); these are persisted on the
order document and surfaced back as Order.shippingOptions.
To send a pre-purchased label instead of asking Riverr to buy postage, pass
shippingLabel — see Prepaid shipping labels.
mutation {
createOrder(
input: {
orderNumber: "ORD-2001"
shopId: "shop_123"
shippingAddress: {
name: "Jane Smith"
address1: "456 Oak Ave"
city: "Los Angeles"
state: "CA"
zip: "90001"
country: "US"
}
shippingOptions: {
carrierCode: "stamps_com"
serviceCode: "usps_priority"
packageCode: "package"
}
orderItems: [
{
productId: "prod_123"
variantId: "var_456"
quantity: 2
price: 29.99
name: "Custom T-Shirt"
}
]
}
) {
id
orderNumber
grandTotal
shipped
cancelled
shippingOptions {
carrierCode
serviceCode
packageCode
}
orderItems {
id
name
price
quantity
}
}
}
Update an Order
updateOrder can mark an order shipped or cancelled, replace the shipping address, change the quantity or variant on an existing line (a size swap), or remove a line by sending quantity: 0.
Address and line edits are rejected once the order has been sent to production. The error message is:
You can't make these changes once the order has been sent to production.
errors[].extensions.code is ORDER_IN_PRODUCTION. Do not retry that edit.
| Change | Allowed while | Rejected when |
|---|---|---|
shippingAddress | The order is not shipped and no shipping label has been purchased. Batching alone does not block an address change. | shipped is true, a label is already on the order (including a prepaid shippingLabel), or the order is partially shipped. |
orderItems (quantity, variantId, or quantity: 0 to remove the line) | No line is batched and statusTags does not include in-production. | Any line is batched, statusTags includes in-production, a label has been purchased, or the order is shipped. Removing the last live line is also rejected. Cancel the order instead. |
cancelled / shipped | Same as before. These flags do not edit the address or the items. |
Orders created with createOrder or createOrderFromGtin stay in Riverr. updateOrder does not call Shopify for those, even when the shop is a Shopify shop.
An order that arrived from Shopify is different. updateOrder writes that change to Shopify in the same call: the new address, the new variant, or quantity: 0 on that line. Riverr then keeps the Shopify result, so a later sync does not put the old line back.
variantId is the Riverr catalog variant id (the same id you pass to createOrder), not the Shopify variant id. It has to be a variant of the same product as that line. Read line ids from getOrder { orderItems { id variantId quantity ignored } }. A Shopify size swap replaces that line, so read the order again for the new line id. A removed line stays on the order with ignored: true and is left out of production.
pre-production in statusTags means the order is still open. in-production means it has been batched and line edits will fail.
mutation {
updateOrder(
id: "order_123"
input: {
shippingAddress: {
name: "Jane Smith"
address1: "456 Oak Ave"
city: "Austin"
state: "TX"
zip: "78701"
country: "US"
countryCode: "US"
}
}
) {
id
shippingAddress {
name
address1
city
state
zip
country
}
}
}
mutation {
updateOrder(
id: "order_123"
input: {
orderItems: [{ id: "order_123_line_1", variantId: "var_large", quantity: 1 }]
}
) {
id
orderItems {
id
variantId
quantity
}
}
}
Remove one line from a multi-item order:
mutation {
updateOrder(
id: "order_123"
input: {
orderItems: [{ id: "order_123_line_2", quantity: 0 }]
}
) {
id
orderItems {
id
quantity
ignored
}
}
}
Marking shipped or cancelled is unchanged:
mutation {
updateOrder(id: "order_123", input: { shipped: true }) {
id
orderNumber
shipped
cancelled
}
}
Create an Order from GTIN
See Finding GTINs for the full guide on creating orders using GTINs.
orderItems[].images.type is an enum — valid values are printing (the artwork
to be printed) and mockup (the visual proof). placement is a string ID; look
up the valid IDs for your enterprise via the getPlacements
query.
mutation {
createOrderFromGtin(
input: {
orderNumber: "ORD-3001"
shopId: "shop_123"
shippingAddress: {
name: "John Doe"
address1: "123 Main St"
city: "New York"
country: "US"
}
shippingOptions: {
carrierCode: "stamps_com"
serviceCode: "usps_priority"
packageCode: "package"
}
orderItems: [
{
gtin: "00123456789012"
quantity: 1
price: 19.99
images: [
{
url: "https://cdn.example.com/artwork.png"
placement: "1"
type: printing
}
{
url: "https://cdn.example.com/mockup.png"
placement: "1"
type: mockup
}
]
}
]
}
) {
id
orderNumber
shipped
shippingOptions {
carrierCode
serviceCode
packageCode
}
orderItems {
id
name
images {
url
placement
type
}
cost {
printingCost
fulfillmentCost
totalCost
}
}
cost {
printingCost
fulfillmentCost
shippingCost
totalCost
}
}
}
Prepaid shipping labels
shippingOptions is a request for Riverr to buy a ShipStation service.
If you already purchased the label (UPS, USPS, ShipStation, EasyPost, etc.),
do not put the label URL on images and do not use
shippingOptions for it. Pass a shippingLabel on
createOrderFromGtin or createOrder.
At ship time Riverr prints the file you sent and skips buying postage. This is the same path CSV / manual orders use.
| Field | Required | Description |
|---|---|---|
shippingLabel.url | yes | Public HTTPS URL to a PNG or PDF. PDF URLs should end in .pdf. |
shippingLabel.carrierName | recommended | Human-readable carrier, e.g. "UPS". |
shippingLabel.carrierService | recommended | Service level, e.g. "Ground". |
shippingLabel.trackingCode | recommended | Tracking number printed on the label. |
Hosting rules match artwork URLs: the link must stay publicly fetchable with no auth, cookies, or expiring signed URLs through print, ship, and any reprint. Riverr stores the URL; it does not copy the bytes at create time.
When shippingLabel is set:
- Leave
shippingOptionsoff (those codes are for a label Riverr would buy). shippingCostcan be0— you already paid the carrier.- After the order ships,
order.shippedfires andShipmentcarries yourtrackingCode/carrierNamewithcost0. Poll Tracking & Fulfillment or subscribe toorder.shippedon Webhooks.
Read the label back on Order.shippingLabel from getOrder /
createOrderFromGtin.
Sample payload with a prepaid label
mutation CreateOrderFromGtin($input: OrderCreateFromGtinInput!) {
createOrderFromGtin(input: $input) {
id
orderNumber
shippingLabel {
url
carrierName
carrierService
trackingCode
}
orderItems {
id
name
images { url placement type }
}
}
}
{
"input": {
"orderNumber": "ORD-3001",
"shopId": "shop_123",
"shippingAddress": {
"name": "John Doe",
"address1": "123 Main St",
"city": "New York",
"state": "NY",
"zip": "10001",
"country": "US"
},
"shippingLabel": {
"url": "https://cdn.example.com/labels/ORD-3001.pdf",
"carrierName": "UPS",
"carrierService": "Ground",
"trackingCode": "1Z999AA10123456784"
},
"orderItems": [
{
"gtin": "00123456789012",
"quantity": 1,
"price": 19.99,
"decorationMethod": "1",
"images": [
{
"url": "https://cdn.example.com/artwork.png",
"placement": "1",
"type": "printing"
},
{
"url": "https://cdn.example.com/mockup.png",
"placement": "1",
"type": "mockup"
}
]
}
]
}
}
url is the field that carries the label. images stay artwork-only
(printing or mockup).