B2B Features
Quote requests, cookie consent, and return requests
Quote Requests
Allow B2B customers to request custom pricing. The contact email is the ownership gate for reading and accepting a quote (quotes carry contact PII and negotiated prices), so keep it available on the confirmation page.
const { data: quote, error } = await client.quotes.submit({
contactName: 'Jan Novak',
contactEmail: '[email protected]',
contactPhone: '+420123456789',
companyName: 'ACME Corp',
message: 'We need bulk pricing for Q3',
items: [
{ productId: 'product-1', quantity: 100, requestedPrice: 80 },
{ productId: 'product-2', quantity: 50 },
],
});
// quote.status: PENDING | QUOTED | ACCEPTED | REJECTED | EXPIREDCheck Status
const { data: status } = await client.quotes.getStatus('quote-id', '[email protected]');
// { id, status, quotedTotal, quotedCurrency, quotedNote, expiresAt, items, ... }Accept Quote
Only a quote in QUOTED status can be accepted; accepting twice is
idempotent and an expired quote flips to EXPIRED:
const { data: accepted } = await client.quotes.accept('quote-id', '[email protected]');Return Requests (EU Withdrawal Button)
EU Directive 2023/2673 (effective 19 June 2026) requires an easy, clearly
labelled online way to withdraw from the contract. Build a public /returns
page with this three-step flow. No customer login is needed; the email used
on the order is the ownership gate.
1. Look Up the Order
The customer enters their order number and email; you get back the internal ids and per-item returnable quantities:
const { data: order, error } = await client.returns.lookupOrder(
'2026-0042',
'[email protected]',
);
// order.items: [{ orderItemId, productName, quantity, returnableQuantity }]Cap each quantity input at returnableQuantity and skip items where it is 0
(already claimed by an active return).
2. Submit the Withdrawal
const { data: returnRequest, error } = await client.returns.submit({
orderId: order.orderId,
email: '[email protected]', // must match the order email
reason: 'CHANGED_MIND', // the 14-day EU default; see all reasons below
customerNote: 'Optional note',
items: [
{ orderItemId: 'item-id', productName: 'Product name', quantity: 1 },
],
});Reasons: CHANGED_MIND, DEFECTIVE, WRONG_ITEM, NOT_AS_DESCRIBED,
TOO_LATE, DUPLICATE_ORDER, OTHER. The platform immediately sends the
acknowledgement email the directive requires; show returnRequest.id to the
customer as their reference number.
3. Check Return Status
const { data: status, error } = await client.returns.getStatus(
'return-id',
'[email protected]',
);
// status.status: REQUESTED | APPROVED | SHIPPED_BACK | RECEIVED |
// REFUNDED | REJECTED | CLOSED
// also: refundAmount, refundedAt, returnTrackingNumber, itemsRun all three calls from Server Actions (or your backend) so the customer's email never appears in a URL.
Cookie Consent (GDPR)
The consent log is append-only (GDPR audit trail); get returns the latest
active consent and resolves to null when none was recorded yet.
// Record consent (visitorId = your anonymous cookie/fingerprint id, 8-128 chars)
await client.consent.record({
visitorId: 'visitor-uuid',
analytics: true,
marketing: false,
preferences: true,
});
// Get the latest active consent — data is null when none exists
const { data: consent } = await client.consent.get('visitor-uuid');
// Revoke (idempotent)
await client.consent.revoke('visitor-uuid');