Expanding responses
Inline related objects to reduce round-trips.
By default the VINR API returns related objects as ID strings to keep responses small and fast. The expand parameter lets you inline the full object in the same response, so you can fetch a payment and its customer, or an invoice and its line items, in a single round-trip instead of two or three.
The expand parameterAsk
Many objects reference others by ID. A payment, for example, carries a customer field holding a cust_ string. To receive the full customer object inline, pass expand with the field path:
import { Vinr } from '@vinr/sdk';
const vinr = new Vinr({ secretKey: process.env.VINR_SECRET_KEY });
const payment = await vinr.payments.retrieve('pay_3Nx8a2Lk', {
expand: ['customer'],
});
// payment.customer is now the full object, not just "cust_8aZ2"
console.log(payment.customer.email);curl https://api.vinr.com/v1/payments/pay_3Nx8a2Lk \
-H "X-Api-Key: $VINR_SECRET_KEY" \
-d "expand[]=customer" \
-Gexpand is an array of strings, so request several fields at once: expand: ['customer', 'refunds']. It works on retrieve, create, update, and list endpoints — anywhere the API returns an expandable object.
Expanding never changes which object you get back, only how much of it is materialized. An unexpanded field is always the ID string; an expanded one is the nested object. Write your code to handle both shapes if the same path is reused across calls.
Expandable fieldsAsk
Each resource documents which of its fields can be expanded. The most commonly used paths:
| Resource | Expandable field | Resolves to |
|---|---|---|
payment | customer | The customer object |
payment | refunds | List of refund objects |
payment | dispute | The dispute object, if any |
invoice | customer | The customer object |
invoice | subscription | The subscription object |
invoice | lines.price | The price on each line item |
subscription | customer | The customer object |
subscription | latest_invoice | The most recent invoice |
redemption | reward | The reward object |
loyalty_account | customer | The customer object |
Fields not listed as expandable return their ID string regardless of what you pass. Requesting an unknown or non-expandable path returns a 400 with code: "invalid_expand".
Nested expansionAsk
Use dot notation to expand through one object into another. For example, a subscription's latest invoice has a customer of its own:
const sub = await vinr.subscriptions.retrieve('sub_9Kpw1Vd', {
expand: ['latest_invoice.customer'],
});
console.log(sub.latest_invoice.customer.email);Expanding a nested path automatically expands its parents — you do not need to also list latest_invoice separately. To expand a field on every element of a list, name the list followed by the field: lines.price expands the price on each line of an invoice.
const invoice = await vinr.invoices.retrieve('inv_2Qm4eRt', {
expand: ['lines.price', 'subscription'],
});
for (const line of invoice.lines) {
console.log(line.price.unit_amount, line.price.currency);
}Expanding inside list responsesAsk
On list endpoints, prefix the path with data to expand the field on each returned object. The expansion applies uniformly to every item in the page:
const payments = await vinr.payments.list({
limit: 20,
expand: ['data.customer'],
});
for (const payment of payments.data) {
console.log(payment.id, payment.customer.email);
}This is the single most effective way to avoid N+1 fetch loops when rendering tables or running reconciliation jobs over a page of results.
LimitsAsk
Expansion is powerful but bounded, so a single request cannot trigger unbounded fan-out:
Prop
Type
Each expanded path adds work to the request and counts toward your rate limit the same as a separate read. Deep or list-wide expansion increases latency — expand only what you render. For large or paginated child collections, prefer the dedicated list endpoint (for example vinr.refunds.list({ payment })) over inline expansion.
Expansion never affects webhook payloads. Events such as payment.completed always deliver the unexpanded object; resolve related records by calling the API from your handler if you need them.
Next stepsAsk
API Reference
Endpoints, parameters, and response shapes for every resource.
Pagination
Cursor-based paging for list endpoints you expand over.
Idempotency
Safely retry create requests without duplicating objects.