Test and launch · 12 of 15
Sandbox
Look up sandbox guarantees, act as the sandbox buyer, and finish a sandbox seller's setup with the account API.
The sandbox is where you test your integration, on every subscription. You need the sandbox 1Password share from Onboard your platform, which holds the sandbox seller’s marketplace API key, its login and authenticator secret, and your sandbox signing secret. The Sandbox quickstart takes a first listing through to a shipped test order.
Sandbox guarantees
Section titled “Sandbox guarantees”The sandbox base URL is https://api-sandbox.snapcaster.ca/api/v1/marketplace.
It is a separate environment that runs only code already running in production.
Snapcaster never resets it, so your platform, seller, marketplace API key, and webhook endpoint persist.
Its catalog is a fixed set of test records that always includes these three SKUs of one product, which every sandbox seller can list:
skuId | productId | Card | Condition |
|---|---|---|---|
14602 | 86 | Abyssal Nightstalker, English | NM |
363348 | 86 | Abyssal Nightstalker, English | LP |
316074 | 86 | Abyssal Nightstalker, English | DM |
A test purchase takes at most 5 lines of at most 10 cards each, and at most 25,000 cents before tax and fees.
Your platform can start 20 test purchases an hour, and the next one returns HTTP 429 RATE_LIMITED with Retry-After.
Payments and payouts use Stripe test mode and move no real money.
Snapcaster marks orders overdue only in production, so in the sandbox you can read dispatch.overdue_at and dispatch.payout_paused but never receive order.dispatch_overdue.
What changes in production lists every other difference.
The sandbox is best-effort and has no uptime SLA. Do not send production traffic or live credentials to it.
Act as the sandbox buyer
Section titled “Act as the sandbox buyer”The sandbox has no buyer app, so Snapcaster’s sandbox buyer acts for you on the orders your own test purchases created.
Each operation behaves like the same action from a real buyer: it sends the same webhooks and moves the order into your next syncToken poll, and a buyer request waits for the same answer from your platform.
Every one takes your seller’s marketplace API key and a UUID Idempotency-Key.
The operations in the table below need an orders or both subscription, and return HTTP 404 ORDER_NOT_FOUND for any order your seller’s own test purchase did not create.
The test purchase itself, POST /sandbox/test-purchases, works for every subscription.
The production API serves none of them.
| The buyer | Operation that acts as the buyer | Your platform answers with |
|---|---|---|
| Asks to cancel the order, or some of its lines | POST /sandbox/orders/{orderId}/cancellation-requests | POST /orders/{orderId}/cancel or POST /orders/{orderId}/cancellation-requests/{requestId}/decline |
| Asks to ship to another address | POST /sandbox/orders/{orderId}/change-requests address_change | POST /orders/{orderId}/change-requests/{requestId}/accept or POST /orders/{orderId}/change-requests/{requestId}/decline |
| Asks to remove lines | POST /sandbox/orders/{orderId}/change-requests cancel_lines | POST /orders/{orderId}/change-requests/{requestId}/accept or POST /orders/{orderId}/change-requests/{requestId}/decline |
| Answers your fulfillment report | POST /sandbox/orders/{orderId}/change-requests/{requestId}/answer | Nothing. Read the order.change_request.resolved and the order.cancelled or order.updated it causes |
Walk each Path B command in this order:
- Push listings for at least two of the SKUs above and buy one with
POST /sandbox/test-purchases. PollGET /sandbox/test-purchases/{ref}untilstatusissucceeded, and take the order id fromorder_idsor fromorder.created. - Raise a buyer request on that order with one of the operations above, and answer it from your platform with the commands in Cancel orders and answer requests. An order holds one pending cancellation request and one pending change request at a time, so start a new test purchase for each request you want to walk side by side. A test purchase ships to Vancouver, BC, and an address change cannot move an order to another province, so send another BC address.
- For a substitution, file a fulfillment report naming the SKU you did not buy, which
GET /orders/{orderId}/substitute-candidateslists for the line, then answer it as the buyer withanswer: "accept". Your receiver getsorder.change_request.resolvedandorder.updatedwithreason: line_substituted.remove_insteadandcancel_orderwalk the buyer’s other two answers. - After each step, run a
syncTokenpass ofGET /orders, and the order comes back with the change.
Finish sandbox seller setup through the account API
Section titled “Finish sandbox seller setup through the account API”The sandbox has no Snapcaster dashboard, so your sandbox seller closes its own browse requirements with account API requests.
They sign in as the seller with the login and authenticator secret from your 1Password share, because the marketplace API key cannot make them.
Every request in this section uses https://api-sandbox.snapcaster.ca/api/v1.
Work through the steps in order, and skip a step when GET /me no longer lists the requirement it closes.
When only CONNECTED_ACCOUNT_CANADIAN, PAYOUTS_READY and OPERATOR_REVIEW_APPROVED are left, finish Stripe onboarding and email info@snapcaster.gg to ask for the store review.
Sign in as the seller
Section titled “Sign in as the seller”Send the seller’s email and password.
The response carries a tempToken, which is valid for five minutes.
curl --request POST \
--url 'https://api-sandbox.snapcaster.ca/api/v1/auth/login' \
--header 'Content-Type: application/json' \
--data '{
"email": "SELLER_EMAIL",
"password": "SELLER_PASSWORD"
}'Send the tempToken with the current code from the authenticator you set up from the share’s authenticator secret.
curl --request POST \
--url 'https://api-sandbox.snapcaster.ca/api/v1/auth/2fa/validate' \
--header 'Content-Type: application/json' \
--data '{
"tempToken": "TEMP_TOKEN",
"token": "AUTHENTICATOR_CODE",
"method": "app"
}'The response carries an accessToken, valid for 15 minutes, which the examples read from the ACCESS_TOKEN shell variable.
Each authenticator code works once, so wait for the next code before you send another request that needs one.
If the login response carries an accessToken and no tempToken, the seller has no authenticator yet, so enrol one first.
Read the open requirements
Section titled “Read the open requirements”curl --request GET \
--url 'https://api-sandbox.snapcaster.ca/api/v1/marketplace/seller/me' \
--header "Authorization: Bearer $ACCESS_TOKEN"data.readiness.incompletePrerequisites lists each open requirement by code, the same list GET /me returns to your platform.
Your platform closes VACATION_DISABLED itself, with PATCH /me.
Enrol an authenticator
Section titled “Enrol an authenticator”This step closes AUTHENTICATOR_ENROLLED.
Start the setup, then add the returned secret or qrCode to an authenticator app and keep the backupCodes somewhere safe.
Send both requests within ten minutes of signing in.
After that they answer 403 CONFIRMATION_REQUIRED, so sign in again first.
curl --request POST \
--url 'https://api-sandbox.snapcaster.ca/api/v1/auth/2fa/app/setup' \
--header "Authorization: Bearer $ACCESS_TOKEN"Confirm the setup with the authenticator’s current code.
curl --request POST \
--url 'https://api-sandbox.snapcaster.ca/api/v1/auth/2fa/app/verify' \
--header "Authorization: Bearer $ACCESS_TOKEN" \
--header 'Content-Type: application/json' \
--data '{
"token": "AUTHENTICATOR_CODE"
}'Accept the Seller Terms
Section titled “Accept the Seller Terms”This step closes CURRENT_SELLER_TERMS_ACCEPTED and accepts the current version of the Seller Terms.
curl --request PATCH \
--url 'https://api-sandbox.snapcaster.ca/api/v1/marketplace/seller/me' \
--header "Authorization: Bearer $ACCESS_TOKEN" \
--header 'Content-Type: application/json' \
--data '{
"termsAccepted": true
}'Declare the tax profile and shipment origin
Section titled “Declare the tax profile and shipment origin”This step closes TAX_PROFILE_COMPLETE and CANADIAN_SHIPMENT_ORIGIN_CONFIRMED.
The sandbox does not copy a tax profile from another environment, so declare one here.
curl --request PATCH \
--url 'https://api-sandbox.snapcaster.ca/api/v1/marketplace/seller/me' \
--header "Authorization: Bearer $ACCESS_TOKEN" \
--header 'Content-Type: application/json' \
--data '{
"identity": {
"sellerType": "business",
"legalName": "Example Cards Inc.",
"addressLine1": "100 King St W",
"city": "Toronto",
"province": "ON",
"postalCode": "M5X 1A9",
"gstHstRegistered": true,
"gstHstNumber": "123456789RT0001"
},
"shipmentOriginCanadaConfirmed": true
}'The identity object replaces the whole tax profile, so send every field each time.
A seller that is not registered for GST/HST sends "gstHstRegistered": false and no gstHstNumber.
The seller cannot withdraw the shipment-origin confirmation.
Accept the GST/HST billing-agent election
Section titled “Accept the GST/HST billing-agent election”This step closes BILLING_AGENT_ELECTION_REQUIRED, which only a GST/HST-registered seller has.
Before accepting, read the election’s terms in data.billingAgentElection.consentText from the seller read above, and send its data.billingAgentElection.effectiveVersion as version.
curl --request PUT \
--url 'https://api-sandbox.snapcaster.ca/api/v1/marketplace/seller/me/billing-agent-election' \
--header "Authorization: Bearer $ACCESS_TOKEN" \
--header 'Content-Type: application/json' \
--data '{
"accepted": true,
"version": "eta-177-1-1-interim-v1"
}'Add a shipping option
Section titled “Add a shipping option”This step closes SHIPPING_OPTION_CONFIGURED.
Set shippingType to letter_mail, bubble_mail or box, and price to the buyer’s shipping charge in integer cents.
Letter Mail is untracked, and the other two types are tracked.
curl --request POST \
--url 'https://api-sandbox.snapcaster.ca/api/v1/marketplace/seller/shipping-options' \
--header "Authorization: Bearer $ACCESS_TOKEN" \
--header 'Content-Type: application/json' \
--data '{
"shippingType": "bubble_mail",
"price": 825
}'Start Stripe Connect onboarding
Section titled “Start Stripe Connect onboarding”This step closes CONNECTED_ACCOUNT_CANADIAN and PAYOUTS_READY once the seller finishes Stripe’s onboarding.
The onboarding link needs a step-up token, so confirm a fresh authenticator code first.
curl --request POST \
--url 'https://api-sandbox.snapcaster.ca/api/v1/auth/step-up' \
--header "Authorization: Bearer $ACCESS_TOKEN" \
--header 'Content-Type: application/json' \
--data '{
"token": "AUTHENTICATOR_CODE"
}'The response carries a stepUpToken, valid for 15 minutes and only for this seller, which the example reads from the STEP_UP_TOKEN shell variable.
curl --request POST \
--url 'https://api-sandbox.snapcaster.ca/api/v1/marketplace/seller/payouts/onboarding-link' \
--header "Authorization: Bearer $ACCESS_TOKEN" \
--header "X-Step-Up-Token: $STEP_UP_TOKEN"Open data.url in a browser to complete Stripe’s test-mode hosted onboarding.
The link works once, so request a new one if it expired or was already opened.
Ship a Path A test order
Section titled “Ship a Path A test order”A Path A platform’s order requests return HTTP 403 SUBSCRIPTION_EXCLUDES_ORDERS, so the seller ships its sandbox test order through the account API.
List the orders waiting to ship and note the test order’s order_id.
curl --request GET \
--url 'https://api-sandbox.snapcaster.ca/api/v1/marketplace/seller/orders?status=created,accepted' \
--header "Authorization: Bearer $ACCESS_TOKEN"Mark it shipped, replacing ORDER_ID with that order_id.
curl --request PATCH \
--url 'https://api-sandbox.snapcaster.ca/api/v1/marketplace/seller/orders/ORDER_ID/fulfillment' \
--header "Authorization: Bearer $ACCESS_TOKEN" \
--header 'Content-Type: application/json' \
--data '{
"status": "shipped",
"trackingCompany": "Canada Post",
"trackingNumber": "7023210039414604"
}'A tracked shipping option needs trackingCompany and trackingNumber, and a Letter Mail order sends neither.
The response shows the order as shipped, and the payout follows the same way as in step 6 of the Sandbox quickstart.
Need help?
The email includes this page and selects sandbox as the environment. Update it if you need help with production.
Never include an API key or signing secret in the message.