Gett Developer Portal
  • Welcome
  • Distribution Partners
  • Brand Partners
  • Commerce Partners
  • Ecosystem Partners
  • Errors
  • API Reference
Documentation
  • Get Started
  • Marketfront SDK
  • API Reference
Resources
  • Payments
Company
  • Gett
  • Terms of Service
  • Privacy Policy

Copyright 2026 Gett. All rights reserved.

Marketfront SDK
Marketfront API
    Getting StartedConventionsOrder LifecycleCatalogSet
    API Reference
Marketfront AI
Shared Guides
powered by Zuplo
Marketfront API

Order Lifecycle

Understand the complete order flow from validation through fulfillment.

Order Flow

Every order goes through two API steps: validation and placement.

Reading the diagram

"Errors?" means isValid: false on the HTTP 200 validateOrder response — business/order problems never produce a 4xx from validate.

End-user client context

Required on every order request

Both order calls require a client object carrying the end user's originating IP and user agent. Requests without it are rejected with a 400 ProblemDetail (errorCode: CLIENT_CONTEXT_REQUIRED).

This is a breaking change for existing integrations. The enforcement date is being communicated to each live partner directly; if you have not received one, contact your Gett integration lead before shipping.

Code
{ "cart": { ... }, "fulfillment": { ... }, "client": { "ip": "203.0.113.7", // the customer's address, not your server's "userAgent": "Mozilla/5.0 (X11; Linux x86_64) Chrome/128.0 Safari/537.36" } }

Your order requests reach Gett server-to-server, so the connection we see belongs to your backend rather than to the person ordering. The commerce partners we forward orders to run anti-fraud checks that need the real customer's signals, so you have to forward them from the request your own front end received — the same request that produced the cart.

We reject rather than substitute a placeholder: a synthetic address forwarded to a partner counts against the integration in the traffic reviews they run, and it would do so silently.

Three named errors cover the field:

errorCodeCause
CLIENT_CONTEXT_REQUIREDclient absent, or ip/userAgent missing or blank
CLIENT_IP_INVALIDip unparseable, or in a range no end user can originate from — private, loopback, link-local, CGNAT, reserved
CLIENT_USER_AGENT_INVALIDuserAgent longer than 512 characters

If your front end sits behind a proxy or CDN, client.ip is the first address in the forwarded-for chain, not your own server's. client is declared on OrderCore, so it applies to validate and place alike — see Schema inheritance.

Validation vs Placement

The API uses a two-step model: a soft pre-check (validateOrder) followed by the committing transaction (placeOrder). Understanding when each returns errors — and in what shape — is central to a correct integration.

How each call behaves

POST /v1/marketfront/orders/validate is a dry run. It computes real server-side pricing and checks availability without writing anything. Think of it like Square's CalculateOrder or Stripe's requirements.errors — a preview you can show to the user before they commit.

  • Always returns HTTP 200 (or 401 for auth failures). There is no 4xx for business/order problems.
  • On 200 the body is the full Order object, including a computed amounts breakdown and an errors[] array.
  • The read-only boolean isValid on the order tells you whether placement is safe to proceed. When isValid: false, errors[] is non-empty and describes what is wrong. When isValid: true and errors is empty, the order passed all checks at that moment.
  • Because validate is read-only it is naturally idempotent — no Idempotency-Key header is required.

POST /v1/marketfront/orders/place is the committing call. It re-validates, charges the customer, and submits the order to the restaurant.

  • On success it returns 2xx with the authoritative post-placement Order.
  • On failure it returns 4xx as an RFC 9457 application/problem+json ProblemDetail. The 400 response covers payment declines, store rejections, and missing idempotency keys; the top-level errorCode field (e.g. PAYMENT_DECLINED, MISSING_IDEMPOTENCY_KEY) names the overall failure reason.

Decision table

SituationEndpointHTTPKey fieldsPartner action
Validate cleanvalidateOrder200isValid: true, errors: [], amounts populatedShow pricing preview; proceed to place
Validate with problemsvalidateOrder200isValid: false, errors[] non-emptySurface errors to user; do not call place
Unknown errors[].code valuevalidateOrder200unrecognized code in errors[]Treat as OTHER; show a generic message
Place successplaceOrder2xxOrder with final amountsConfirm order to user; start tracking
Place hard failureplaceOrder4xxProblemDetail + top-level errorCode + errors[]Handle per errorCode; retry with same idempotency key only for PAYMENT_FAILED
Malformed requestEither400 / 422ProblemDetailFix request body before retrying

A clean validate does not guarantee place succeeds

Stock levels, prices, and payment authorization can change in the window between the two calls. Always inspect errors even on a 200 validate response, and always be prepared for placeOrder to return a 4xx even after a successful validate.

Unified OrderError shape

OrderError is the same object on both paths — order.errors[] on a validate 200 and ProblemDetail.errors[] on a place 4xx. You only need one error-rendering path in your client:

FieldTypeDescription
codestring (open enum)Machine-readable reason — see Error codes below
messagestringCurated, user-facing description
pointerstringRFC 6901 JSON Pointer to the offending element, e.g. /cart/lineItems/0

Note the distinction between OrderError.code (per-element, in errors[]) and the top-level ProblemDetail.errorCode (single string naming the overall place failure). Both can appear on a 4xx place response but they serve different purposes.

Error codes

errors[].code is an open enum (x-extensible-enum). The list below is the current set, but it is not exhaustive — Gett may add new codes at any time as new failure modes are identified. Following the Zalando API extension convention: clients must provide default/fallback behaviour for unknown values (route to OTHER) and must not hard-fail or throw on an unrecognized code. Do not deserialize into a closed/strict enum type.

CodeMeaningSuggested action
ITEM_UNAVAILABLEAn item in the cart is no longer availableRemove the item and re-validate
PAYMENT_FAILEDTransient payment processing failureRetry place with the same idempotency key
STORE_CLOSEDStore is not accepting orders right nowRe-discover stores or try a scheduled order
DELIVERY_UNAVAILABLEDelivery is not available for this orderOffer pickup or a different store
OUTSIDE_AVAILABILITY_WINDOWRequested scheduled time is outside the store's hoursAdjust scheduledTime or switch to ASAP
MINIMUM_NOT_METOrder total is below the store's minimumAdd more items
ORDER_TOTAL_DIFFERENTTotal changed since the order was last validatedRe-validate to get the updated amounts
OTHERCatch-all for any reason not covered above, and the fallback for unrecognized codesShow a generic error message

Order State & Status

Orders use two fields: state (lifecycle position) and status (granular progress).

State

Status

Within the open state, status tracks progress:

For complete details on state values, status values, and error codes, see the API Reference.

Fulfillment

Every order carries a fulfillment object that is a discriminated union on the mode property. The two variants are PICKUP and DELIVERY_BY_MERCHANT.

Common fields (all variants)

FieldRequiredDescription
modeYesDiscriminator: PICKUP or DELIVERY_BY_MERCHANT
scheduleTypeYesASAP or SCHEDULED
scheduledTimeConditionalUTC ISO-8601 date-time. Required when scheduleType is SCHEDULED; must be null (or omitted) when ASAP.

Delivery-only fields (DELIVERY_BY_MERCHANT)

FieldRequiredDescription
addressYesDelivery destination. On a request, provide either an addressId reference or inline street fields. On a response, the fully resolved and geocoded address is returned.
deliveryTypeYesDOOR_TO_DOOR or LEAVE_AT_DOOR
instructionsNoFree-text delivery instructions, max 500 characters

Examples

PICKUP — ASAP

Code
{ "fulfillment": { "mode": "PICKUP", "scheduleType": "ASAP" } }

DELIVERY_BY_MERCHANT — scheduled

Code
{ "fulfillment": { "mode": "DELIVERY_BY_MERCHANT", "scheduleType": "SCHEDULED", "scheduledTime": "2025-09-15T19:30:00Z", "address": { "address1": "123 Main St", "address2": "Apt 4B", "city": "New York", "state": "NY", "postalCode": "10001" }, "deliveryType": "DOOR_TO_DOOR", "instructions": "Leave at the front desk" } }

Fulfillment vs store discovery

The fulfillment object on an order (discriminated union above) is distinct from the fulfillmentType flat enum (PICKUP | DELIVERY_BY_MERCHANT) used on DiscoverStoresRequest to filter search results. They share the same values but serve different purposes — one describes how to fulfill a specific order, the other filters which stores to surface.

Idempotency

POST /v1/marketfront/orders/place requires an Idempotency-Key header. Calls without it are rejected with a 400 ProblemDetail (errorCode: MISSING_IDEMPOTENCY_KEY).

  • Generate a fresh UUID v4 per distinct order and include it on every retry of that order.
  • A replay with the same key returns the original response (24h TTL) — safe to retry on network errors and 5xx without risking a duplicate charge.
  • Do not reuse a key with a different payload. Today the cached response is returned regardless of body; a future release will reject same-key/different-body with 422. Keep keys 1:1 with payloads now to avoid surprises.

validate is naturally idempotent (read-only pricing) and does not use the header.

Related

  • Validate Order — Check availability and pricing
  • Place Order — Submit order for fulfillment
  • Payments — Payment options and Card-on-File setup
  • Webhooks — Signature verification and retry policy for order status webhooks
ConventionsCatalogSet
On this page
  • Order Flow
  • End-user client context
  • Validation vs Placement
    • How each call behaves
    • Decision table
    • Unified OrderError shape
    • Error codes
  • Order State & Status
    • State
    • Status
  • Fulfillment
    • Common fields (all variants)
    • Delivery-only fields (DELIVERY_BY_MERCHANT)
    • Examples
  • Idempotency
  • Related
JSON
JSON
JSON