Migrating from another commerce vendor
If you’re moving from another commerce orchestration vendor or rolling off a homegrown integration, this guide is the rough translation layer. It’s not platform-specific — every commerce vendor has its own quirks — but it covers the shape of the migration.
For platform-specific guidance, see Supported platforms.
Conceptual mapping
| You probably have today | Firmly equivalent |
|---|---|
| A way to authenticate as a client app | Browser session or server-to-server |
| A product / catalog search API | Discovery search and Catalog |
| A cart object with line items | Cart management |
| Shipping address + method selection | Set shipping info + Set shipping method |
| A payment tokenization step | Get payment public key + JWE encryption client-side |
| A “place order” / “submit order” call | Place order (v2) |
| Per-merchant API integrations | Single integration → access all Firmly-connected merchants |
| Tax + shipping calculation on your side | Merchant-driven calculation via Firmly (you don’t compute) |
What changes structurally
1. One integration, many merchants
If your previous vendor required per-merchant authentication or per-merchant API setup, that goes away. With Firmly, the destination has a single _appId. The merchant is identified by the domain parameter in each call. Adding a new merchant is a Firmly-side configuration change — no code on the destination side.
2. Cart state lives at Firmly’s edge
Cart state is stored in Firmly’s edge session store. Your previous vendor may have required you to maintain cart state on your side; with Firmly you can — but you don’t have to. The cart can be retrieved at any time via Get Cart.
3. Payment data flow is JWE-encrypted, not PCI-on-your-side
Card data is encrypted client-side using Firmly’s RSA public key before transit. Your code handles JWE encryption with a Firmly-provided public key; the encrypted blob travels through your servers but you never see (or have to PCI-scope) the plaintext PAN.
If your previous integration used a hosted-checkout pattern (the user filled card data on the vendor’s page), the equivalent on Firmly is Hosted checkout.
4. Carts are scoped to one merchant
Firmly carts hold multi-product items from a single merchant. To reach several merchants, place one order per merchant.
5. Firmly’s scope ends at order placement
Once place-order returns success, Firmly’s role is done. Anything beyond that lives entirely on the merchant’s side.
What stays the same
- HTTPS REST patterns
- JSON request and response bodies
- Standard HTTP status codes
- Authentication via header
- Idempotency keys for safety on mutations
- Multi-step cart and checkout flow
If your previous vendor was REST-based, the call patterns and conventions will feel familiar. The data shapes differ; the protocol shape doesn’t.
Migration sequence
A typical migration goes through these phases:
- Sandbox setup — get your sandbox App ID and a test merchant. Run Sandbox setup end-to-end to confirm connectivity
- Catalog translation — map your existing product references to Firmly’s discovery + catalog APIs
- Cart translation — map your cart object to Firmly’s cart shape
- Payment translation — implement JWE encryption client-side. See Get Payment Public Key
- Place-order translation — replace your “submit order” call with Place order (v2). Send
Idempotency-Keyon every attempt, and guard retries by re-readingcart_statusfirst (see Idempotency) - Cutover — when sandbox runs cleanly, swap sandbox
_appIdfor production_appIdand swap test merchant domains for live merchant domains. No deployment of a “production SDK” — it’s the same API, different credentials
Things to watch for during migration
- Currency formatting: money values come as a decimal in
value(e.g.99.99) and integer cents innumber(e.g.9999), plus asymbolandcurrency. Display usesvalue; do arithmetic onnumberto avoid floating-point rounding - Multi-shipment: Even single-product carts can have multiple
shipment_ids if the merchant ships from different warehouses. Walk each shipment for availability and method - Promo behavior: A 200 response on
add-promo-codesdoesn’t mean the code applied — re-read the cart and check the field the promo moves (sub_totalfor line-item discounts,total/cart_discountfor order-level and free-shipping promos) - Idempotency keys: Use the same key on retries of the same attempt; new key only on a genuinely new attempt. Note the key is deduplicated only on the UCP protocol bridge today — on the core REST endpoints, re-read the cart before retrying
- Order placement is atomic: Once
place-orderreturns 200 withcart_status: "submitted", the order is at the merchant — never retry after asubmittedresponse
When you might NOT want to migrate
- Your previous integration involves a single merchant on a stable in-house platform — direct integration may stay simpler than going through a layer
- You need features Firmly doesn’t have (subscriptions, B2B procurement workflows)
- Your destination is a category Firmly doesn’t serve today (travel bookings, ticketing, healthcare prescriptions)
In those cases, the migration cost outweighs the benefit. Talk to Firmly if you’re not sure.
Related
- How Firmly Works — the conceptual map
- Sandbox setup — first stop in any migration
- Cart API guide — the multi-step cart flow in detail
- Errors & Conventions — recovery patterns