What the account behind this credential has, what it still needs, and the one thing to do next — so an agent setting up a merchant learns it up front instead of as a refusal on the call it was making. ready says whether each way of selling would be accepted now: live_orders (a live key, a card on file, and an account not held to sandbox; otherwise a live order is refused with 402 no_payment_method or 403 sandbox_only); hosted_sales and store_orders are always false here, where orders arrive through this API and its dashboard only. steps lists each step with whether it is done, measured from the account's own rows rather than ticked by hand, and the dashboard page that completes it; next_action is the first required step not yet done, or null. Optional steps (the webhook, and a live key of your own) are ones the first live order does not need, and never the next action. Which steps are required depends on the credential asking: on a live one (a live key, or an OAuth sign-in, which is always live) the only required step is a card on file and live_key reads done; on a test key every step is optional and next_action is null, since its $0 orders need nothing. Requires no scope, like GET /me: the narrowly scoped key that was just refused is the one that most needs to learn why. Reports booleans and dashboard links only — no card, payout or customer detail — and changes nothing.
- Credential
- An API key in
x-api-key - Scopes
- None: every key may call it
Request
GET /api/v1/setup
curl "https://portal.printedsimply.com/api/v1/setup" \
-H "x-api-key: ps_test_YOUR_KEY"Response 200
Readiness by way of selling, every setup step, and the next action
data
readyobjectrequiredWhether each way of selling would be accepted right now — the same condition the refusing route checks.
ready.live_ordersbooleanrequiredA live key — the credential asking, when it is a live one (a live key or an OAuth sign-in), and otherwise one you made on the API keys page that is not revoked or expired (the key the
live_keystep counts) — a card on file, and an account not held to sandbox.ready.hosted_salesbooleanrequiredAlways false here: orders reach this portal through this API and its dashboard only.
ready.store_ordersbooleanrequiredAlways false here: orders reach this portal through this API and its dashboard only.
sandbox_onlybooleanrequiredHeld to test mode by the platform; live orders are refused until support lifts it.
stepsobject[]requiredEvery setup step in order, each measured from the account's rows.
steps[].keystringrequiredOne of
test_keysandbox_orderwebhookpayment_methodlive_keyfirst_salesteps[].labelstringrequiredsteps[].hintstringrequiredWhat completing the step does, and what is refused until it is done.
steps[].donebooleanrequiredsteps[].optionalbooleanrequiredA step the first live order does not need: the webhook (GET /order/{id} reads the same state), and a live key of your own (a real order placed from the dashboard's order page uses the key that page makes). Asked by a live credential, every step but the card is optional; asked by a test key, every step is. Never holds back
complete, and never the next action.steps[].dashboard_urlstring (uri)requiredThe dashboard page that completes it.
next_actionobject | anyrequiredThe first required step not yet done, or null when every required step is done.
next_action.keystringrequiredOne of
test_keysandbox_orderwebhookpayment_methodlive_keyfirst_salenext_action.labelstringrequirednext_action.hintstringrequirednext_action.dashboard_urlstring (uri)requiredcompletebooleanrequiredEvery required step is done. Optional steps never hold this back.
meta
pageintegertotalintegerlimitintegerThe page size actually applied, which is not necessarily the one asked for — the operation's own ceiling wins.
pagesintegertotaloverlimit, rounded up.next_cursorstring | nullOn a cursor-paged operation: send this back as
cursorfor the next page. Null on the last page. Absent on operations that do not page by cursor.has_morebooleanOn a list operation whose
metaisListMeta: whether another page follows this one.
{
"status": "success",
"data": {
"ready": {
"live_orders": false,
"hosted_sales": false,
"store_orders": false
},
"sandbox_only": false,
"steps": [
{
"key": "test_key",
"label": "Create your test key",
"hint": "It starts with ps_test_ and places $0 orders that are never printed or charged. It is made on the API keys page and shown in full once, when it is made.",
"done": true,
"optional": true,
"dashboard_url": "https://portal.printedsimply.com/dashboard/api-keys"
},
{
"key": "sandbox_order",
"label": "Send a $0 test order",
"hint": "Send POST /v1/order with a test key. The order runs to delivered on a compressed clock, with a tracking link; nothing is printed or charged.",
"done": false,
"optional": true,
"dashboard_url": "https://portal.printedsimply.com/dashboard"
},
{
"key": "webhook",
"label": "Add a webhook and watch the order move",
"hint": "We send a signed event to your URL as each order moves, test orders included, and keep a delivery log you can replay. No server yet? A hosted test inbox receives your test events for you, with nothing to install and no tunnel.",
"done": false,
"optional": true,
"dashboard_url": "https://portal.printedsimply.com/dashboard/webhooks"
},
{
"key": "payment_method",
"label": "Add a card",
"hint": "A live order is charged to the card on file when it is placed; without one it is refused with no_payment_method. Test orders never need one.",
"done": false,
"optional": true,
"dashboard_url": "https://portal.printedsimply.com/dashboard/billing#payment-method"
},
{
"key": "live_key",
"label": "Create a live key",
"hint": "It starts with ps_live_ and places real orders. Your code does not change, only the key.",
"done": true,
"optional": true,
"dashboard_url": "https://portal.printedsimply.com/dashboard/api-keys"
},
{
"key": "first_sale",
"label": "Send your first live order",
"hint": "Send POST /v1/order with your live key, your own artwork (an https link or an uploaded asset id) and a real address, and it is printed in our US plant and shipped.",
"done": false,
"optional": true,
"dashboard_url": "https://portal.printedsimply.com/dashboard/orders"
}
],
"next_action": null,
"complete": true
},
"request_id": "4e3753e1-48dd-4313-bfd8-48e4af4e116a"
}Errors
Missing, invalid or expired API key:
missing_api_key(none sent),invalid_api_key(unknown or revoked),key_expired(past the expiry set when it was created; create a new key).Rate limit exceeded. Two windows can produce this status and
error.codesays which:rate_limit_exceededfor the per-minute sliding window,daily_quota_exceededfor the plan's daily quota. Both carryRetry-After; the daily one also carriesX-Daily-LimitandX-Daily-Remaining. The per-minute limits are plan-based — see Rate Limits above, or call GET /v1/me for this credential's own figures.internal_error — the account's setup could not be read. Nothing is reported rather than a list of wrong claims; retry shortly.