Expanding responses
expand adds a related record to a read or to every row of a list, so you don't fetch each one separately. Each list accepts its own paths, each path needs a read scope, and expansion never changes which rows a page holds.
Expand a list#
Many merchant lists accept expand, which adds a related record to every row of the page. A returns desk can show each return's order number and buyer email from one GET /v1/returns request instead of reading every order. Pass paths as repeated keys, as in expand=order&expand=customer, or comma-separated, as in expand=order,customer.
curl "https://api.withflintpay.com/v1/returns?status=requested&expand=order,customer" \
-H "Authorization: Bearer YOUR_API_KEY"
{
"data": [
{
"return_id": "ret_01KEZF7C00VDTZH2NK73DBK2HZ",
"return_number": "R-1001",
"status": "requested",
"order_id": "ord_01KEZF7C00RWKW7JDYTZ5A6ET0",
"order": {
"order_id": "ord_01KEZF7C00RWKW7JDYTZ5A6ET0",
"order_number": "1001",
"status": "open",
"payment_status": "paid",
"refund_status": "none",
"buyer_contact": {
"email": "guest@example.com",
"phone": null,
"is_email_cleared": false,
"is_phone_cleared": false
}
},
"customer": null
}
],
"request_id": "req_01KWM6WAHG3N9Q8T2V5XRZ7C4D"
}
The response is abridged. Each row keeps its ID field and gains the related record beside it under the path name. This return is on a guest order, so it has no customer_id and customer is null. A path you don't request is left out.
The order summary includes buyer_contact when the order recorded an email or phone, including a guest order with no customer. It is the contact saved on the order when payment started, so it doesn't follow later changes to a customer's email, and it is left out when the order recorded none. See Orders.
An expanded record matches the same path expanded on the resource's own read, so order on a return in the list equals order on GET /v1/returns/{return_id}?expand=order.
How a page is expanded#
Flint builds the page first, with your filters, sort, and page_size, then reads each requested path in one batch for the distinct IDs on that page. Twenty returns that belong to eight orders cost one read of eight orders. Expansion never changes which rows a page contains, their order, or their IDs.
A page succeeds or fails as a whole, so you never get some rows expanded and others not:
- If a service an expansion depends on is unavailable, the request returns
503 SERVICE_UNAVAILABLEwithparam: expand. Retry the same request. - If a row references a record Flint can't find, the request returns
500 INTERNAL_ERROR. Retry, or read the page without that path, and contact support with therequest_id.
Each list accepts only the paths listed for it in Lists that accept expand. Any other path, including a nested one such as order.customer, returns 400 INVALID_REQUEST with detail code INVALID_VALUE and param: expand. A request can name at most 10 paths.
Expansion and the cursor#
The cursor doesn't record expand, so you can add or drop an expansion between pages without restarting the run. A run over GET /v1/credit-notes?reason=billing_error can request its next page with expand=invoice added and the same page_token.
Scopes and credentials#
Each path needs the list's read scope and the read scope of the record it includes. GET /v1/returns?expand=order needs commerce.returns.read and commerce.orders.read. A key without one of them gets 403 INSUFFICIENT_SCOPE with param: expand, and no rows. Dashboard sessions follow the user's role.
These list paths are for merchant callers: secret API keys, partner install tokens, and dashboard sessions. Customer sessions and checkout session credentials keep their own expand rules, and order summaries in /v1/me responses don't include buyer_contact.
Expand a single read#
A resource's own read takes expand the same way. GET /v1/returns/{return_id}?expand=order returns the return with its order, and it can accept more paths than the return list does, including shipments and return_receipts. Each endpoint's reference lists its own paths, and the table below covers lists only.
Lists that accept expand#
Each path needs the list scope plus any scope shown beside it.
List (GET) | List scope | expand paths |
|---|---|---|
/v1/balance-transactions | money_movement.balance_transactions.read | order (+ commerce.orders.read) |
/v1/bundles | commerce.bundles.read | modifier_set (+ commerce.catalog.read) |
/v1/checkout-sessions | checkouts.checkout_sessions.read | customer (+ customers.read), invoice (+ commerce.invoices.read), order (+ commerce.orders.read), payment_link (+ checkouts.payment_links.read) |
/v1/credit-notes | commerce.credit_notes.read | invoice (+ commerce.invoices.read) |
/v1/customers | customers.read | default_payment_method (+ payments.payment_methods.read), receivables |
/v1/disputes | payments.disputes.read | customer (+ customers.read), order (+ commerce.orders.read), payment_intent (+ payments.payment_intents.read) |
/v1/fraud-warnings | risk.read | dispute (+ payments.disputes.read), payment_intent (+ payments.payment_intents.read) |
/v1/fulfillment-events | commerce.orders.read | order |
/v1/fulfillment-notifications | commerce.orders.read | order |
/v1/fulfillments | commerce.orders.read | order |
/v1/inventory-levels | commerce.inventory.read | inventory_item |
/v1/inventory-movements | commerce.inventory.read | inventory_item |
/v1/invoices | commerce.invoices.read | customer (+ customers.read), order (+ commerce.orders.read) |
/v1/orders | commerce.orders.read | customer (+ customers.read), subscription (+ commerce.subscriptions.read), subscription_plan (+ commerce.subscription_plans.read) |
/v1/organizations | accounts.organizations.read | parent_organization |
/v1/packages | commerce.orders.read | order |
/v1/packages/{package_id}/items | commerce.orders.read | order |
/v1/payment-intents | payments.payment_intents.read | customer (+ customers.read), invoice (+ commerce.invoices.read), order (+ commerce.orders.read) |
/v1/payment-links | checkouts.payment_links.read | sales_summary, subscription_plan (+ commerce.subscription_plans.read) |
/v1/payment-methods | payments.payment_methods.read | customer (+ customers.read) |
/v1/payment-reviews | risk.read | customer (+ customers.read), order (+ commerce.orders.read), payment_intent (+ payments.payment_intents.read) |
/v1/payouts | money_movement.payouts.read | original_payout, payout_destination (+ money_movement.payout_settings.read), reversed_by_payout |
/v1/products | commerce.products.read | modifier_set (+ commerce.catalog.read) |
/v1/products/{product_id}/variants | commerce.products.read | modifier_set (+ commerce.catalog.read) |
/v1/promotion-codes | commerce.promotions.read | promotion |
/v1/refunds | commerce.refunds.read | customer (+ customers.read), order (+ commerce.orders.read), payment_intent (+ payments.payment_intents.read) |
/v1/return-policies | commerce.returns.read | current_revision |
/v1/return-resolutions | commerce.returns.read | replacement_order (+ commerce.orders.read) |
/v1/returns | commerce.returns.read | customer (+ customers.read), order (+ commerce.orders.read) |
/v1/shipments | commerce.orders.read | order |
/v1/subscriptions | commerce.subscriptions.read | customer (+ customers.read), payment_method (+ payments.payment_methods.read), subscription_plan (+ commerce.subscription_plans.read) |
