Docs
Firmly Agentic Commerce
Set theme to dark (⇧+D)

Sandbox Setup

This page is the prerequisite for the Advanced Checkout Guide. It walks you through getting credentials, choosing a test merchant, and validating your environment with a curl call.

​​ What you need from Firmly

Email firmlydocs@firmly.ai and ask for:

  1. A sandbox App ID (_appId) — a UUID scoped to a non-production environment
  2. A test merchant domain — typically something like staging.luma.gift
  3. Optional: a server-to-server secret — if you plan to use S2S auth instead of browser sessions
  4. Optional: an Agentic Pay API token — if you plan to enroll cards and pay with network tokens. See Agentic Pay in the sandbox

Firmly will provision these and confirm the test merchant has a non-empty catalog you can search and buy from.

​​ Endpoints

Surface Host
General API (auth, discovery, cart, checkout, orders) https://api.firmly.work
Payment (public key, place-order) https://cc.firmly.work

These are the sandbox base URLs. Production runs on different hosts from the sandbox. Firmly provides your production base URLs at go-live — plan for a configuration change, not just a new App ID. Going live changes your App ID, your merchants, and your base URLs. For the embedded / hosted checkout drop-in URL, contact Firmly.

​​ Test cards

Firmly accepts these public sandbox cards against test merchants:

Card number Brand What it tests
4111111111111111 Visa Successful payment
4000000000000002 Visa Generic decline
4000000000009995 Visa Insufficient funds decline
4000000000000069 Visa Expired card decline

Use any future date (e.g. 12 / 2030), any 3-digit CVV, and any cardholder name. These cards only work against sandbox merchants — real merchants reject them.

​​ Verify your setup with curl

Once you have your _appId and a test merchant domain, run these three calls. If all three succeed, you’re ready to run the Advanced Checkout Guide.

​​ 1. Bootstrap a session


curl -X POST https://api.firmly.work/api/v1/browser-session \
-H "x-firmly-app-id: YOUR_APP_ID"

YOUR_APP_ID is the UUID Firmly provisioned for you — it looks like xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, not a short slug. Substitute the exact value Firmly sent.

Expected: a JSON response with access_token, device_id, expires_in. Save the access_token as $TOKEN.

​​ 2. Search the test merchant catalog

Scope the search to your paired test merchant with filters.domains so you’re verifying that specific merchant’s catalog:


curl -X POST https://api.firmly.work/api/v1/discovery/search \
-H "x-firmly-authorization: $TOKEN" \
-H "Content-Type: application/json" \
-d '{"query": "gift", "filters": {"domains": ["staging.luma.gift"]}, "page_size": 3}'

Expected: a JSON response with a products array. Each product carries a domain field — it should match the test merchant domain you queried (staging.luma.gift above).

Empty products array? Ask Firmly to load sample products for your test merchant.

​​ 3. Get the payment public key


curl "https://cc.firmly.work/api/v1/payment/key?format=JWK"

Expected: an RSA JWK with kty, n, e, and a kid (key ID). No auth needed for this endpoint.

If all three return 200s with sensible bodies, your sandbox is live.

​​ Common setup errors

What you see Why Fix
401 on browser-session App ID isn’t recognized in this environment Confirm you’re using the sandbox App ID, not production
404 ucp_disabled on search Merchant hasn’t opted into the relevant surface Ask Firmly to enable it for the test merchant
404 DomainNotFound Domain typo or wrong environment Verify the exact domain string from Firmly
Empty products array Merchant has no products in catalog Ask Firmly to load sample products into the test merchant
Network failure on cc.firmly.work Outbound HTTPS to payment domain is blocked Add cc.firmly.work to your allowlist alongside api.firmly.work
400 InvalidAPIToken on /wallets/agentic-pay/* You sent the browser-session access_token (or a production token) instead of the Agentic Pay API token Use the Agentic Pay API token Firmly issued for the sandbox in x-firmly-authorization
409 PaymentMethodNotAvailable on /enroll The card’s network is not enabled for your destination, or the card is not a network sandbox test card Ask Firmly to enable the network on your token; enroll only the network sandbox test cards Firmly provided

​​ Agentic Pay in the sandbox

Agentic Pay — enrolling a cardholder’s card and paying with a network token — runs on the sandbox hosts listed above (api.firmly.work for enrollment and intent, cc.firmly.work for order placement) against the test merchant. It needs one more credential and different test cards.

​​ What you need

  1. An Agentic Pay API token — sent as x-firmly-authorization on the /api/v1/wallets/agentic-pay/* endpoints. This is an app-level token, not the browser-session access_token. Request it from firmlydocs@firmly.ai together with your sandbox App ID, and say which card networks you want enabled (Visa, Mastercard, Discover). Networks are enabled per destination; a card on a network that is not enabled returns 409 PaymentMethodNotAvailable.
  2. Network sandbox test cards — enrollment tokenizes the card at the card network’s sandbox, so the generic test cards above are not enrollable there. Firmly provides network sandbox test cards for each enabled network along with your token.
  3. Your sandbox App ID and a device session — still required. Order placement (/wallet-complete-order) is authenticated with the device session token from Browser Session, exactly as for card payments.

​​ Verify your token with curl

Enrolling a card is the quickest proof that the token is valid and the network is enabled. Use a network sandbox test card Firmly provided:


curl -s -X POST https://api.firmly.work/api/v1/wallets/agentic-pay/enroll \
-H "x-firmly-authorization: $AGENTIC_PAY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"pan": "<network sandbox test card>", "expiry_month": "12", "expiry_year": "2030", "cvv": "123", "consumer": {"email": "cardholder@example.com", "country_code": "US"}}'

Expected: 200 with a flow_token, a virtual_card_id, and verification_methods (empty for Discover). A 400 InvalidAPIToken means the token is wrong for this environment; a 409 PaymentMethodNotAvailable means the network is not enabled for your destination or the card is not a sandbox test card.

​​ Browser pieces in the sandbox

Visa and Mastercard verification runs in a network-hosted iframe in the cardholder’s browser. In the sandbox those iframes are served from the networks’ sandbox hosts, and the result comes back through Firmly’s Iframe Callback bridge on api.firmly.work. If you use the Headless SDK, configure it for the sandbox as:

  • baseUrl — https://api.firmly.work
  • iframeOrigins — the Firmly bridge origin plus the network sandbox iframe origins. These are the values Firmly’s wallet service ships for the sandbox and injects into the hosted SDK bundle (GET https://api.firmly.work/api/v1/wallets/sdk/js?appId=<your App ID>, as window.__FIRMLY_AGENTIC_PAY_CONFIG__.iframeOrigins); load that bundle, or copy its values, rather than hard-coding hosts — currently https://api.firmly.work, https://sandbox.src.mastercard.com, https://sbx.vts.auth.visa.com
  • bridgeUrl — https://api.firmly.work/api/v1/wallets/agentic-pay/iframe-callback
  • vaultBaseUrl — https://cc.firmly.work
  • merchantDomain — staging.luma.gift

Discover has no iframe step, so a Discover enrollment and intent can be exercised entirely with curl.

​​ Run the full flow

The Agentic Pay Integration guide walks the complete chain — enroll → verify → intent → order — against this sandbox and the test merchant. Create the cart first (session → add line item → set shipping) exactly as in the Advanced Checkout Guide; the Agentic Pay steps replace only the JWE card payment.

​​ Going from sandbox to production

When you’re ready to go live:

  1. Request a production App ID from Firmly
  2. Confirm the live merchants you’ll transact against — a production App ID is typically scoped to a specific set of merchants
  3. Stop using the test cards above; production requires real cards or wallet-based payments
  4. If you use Agentic Pay, request a production Agentic Pay API token and switch the SDK iframeOrigins to the networks’ production hosts, which Firmly provides at go-live

Going live is a configuration change for your application, plus the Firmly-side onboarding of any production merchants. There’s no separate “production SDK” to install.

​​ Next steps