Skip to main content
An order is one purchase: domains plus Google and/or Microsoft inboxes routed to one workspace target. IDs look like ord_01HZX. Use a saved bundle or custom license counts, never both.

Order flow

Connect a reusable workspace with POST /workspaces, then send its provider and wrk_... ID to POST /orders. Workspace creation does not use an Idempotency-Key. Each order does.

Acceptance and funding

Each call submits one order. New orders return HTTP 200 with the complete order receipt after validation, final pricing, and the wallet debit are saved:
Poll GET /orders/{order_id} to follow the order. Its processing.phase is queued, waiting_for_funds, preparing, provisioning, or failed. Completed and cancelled orders omit processing. The quoted cost is available while the order waits. After a successful receipt, repeating the same POST with the same idempotency key returns HTTP 200 with the same funded order and created.order: false. A retry that first completes funding can return created.order: true; it still refers to the same order and debit. HTTP success confirms order submission; order.status reports inbox setup progress. Purchase domains must pass the availability and non-premium checks before acceptance. Unavailable, premium, or unverified names reject the entire request. Orders priced from registrar cost also require a valid quote. Availability can change after the check; acceptance does not mean a registrar purchase has completed. Orders from nearby calls are funded together internally, with a separate debit for each order. Wallet holds and the configured balance floor still apply. A smaller affordable order may proceed while an older, larger order waits. An order that cannot be funded returns HTTP 402 without a successful order ID. If automatic top-up or a fresh availability check is pending, the API returns HTTP 409 with idempotency_in_progress and Retry-After: 5. Retry the unchanged request with the same Idempotency-Key; do not submit a new order. A pending response can later become a funded order or a definitive failure. Automatic top-up uses one pending payment per wallet. An unpaid order waits up to 15 minutes; disabled or blocked top-up fails it sooner. Failed unpaid orders release their domain claims. A payment confirmed after expiry credits the wallet but does not restart the expired order. Once funded, order setup resumes from saved progress without a second debit. Do not create a new idempotency key just because setup is still running. For Smartlead, the workspace ID always points to the connected main workspace. Omit destination.client_id to use the main workspace. Include it to use one client workspace. Orders never accept Smartlead login credentials, user data, or customer data. A Smartlead Google order does not need the optional workspace login pair. A Smartlead Microsoft or mixed order does. See Provider setup and ordering.

Statuses

Subscribe to order.* webhooks, or poll GET /orders/{id}.
Open blockers set action_required. There is no order.action_required webhook. Poll GET /orders/pending instead.

How many domains you need

For example, 20 Google domains with google_licenses: 2 creates 40 Google inboxes. Bundled orders use the google_licenses value saved on the bundle. Add quantity: 2 to buy two copies: a 20-domain bundle then requires 40 submitted domains and creates twice the inboxes. Quantity defaults to 1 and is not valid on custom orders.

Mixed orders

Send one flat domains list. Peeker assigns each domain from its usable_for values. Do not label domains by mailbox type.

Personas and usernames

Every persona needs first_name and last_name. For Google inboxes, you may also send usernames, which are the mailbox names before @. Peeker keeps every supplied username and generates any missing seats. If one persona receives two Google seats and supplies usernames: ["connor"], Peeker uses connor for one seat and generates the other. Send ["connor", "connorscale"] to control both. Supplied usernames must be unique and cannot outnumber the seats assigned to that persona.

Domains you already own

  1. Import first with POST /domains/import (or the async jobs route).
  2. Unimported names are treated as registration candidates.
  3. Blocked domains fail before wallet debit with domains_not_submittable.
Common reasons: unavailable, premium, unknown, provider_error, already_in_use, stale.

Idempotency

On retryable 503 or 500, keep the same key and body. A replay of a successful order returns created.order: false; the first successful funding can return true. If the initial authorization read remains unavailable after three attempts, the API preserves its existing 500 internal_error response before creating an order or charging the wallet. Invalid or revoked keys are not retried. For a Smartlead Microsoft or PlusVibe 422 provider_login_credentials_required, repair the connected workspace first, then retry the unchanged order with its original key. Smartlead orders do not accept destination.login_credentials. Any other field change returns 409 idempotency_conflict.

Pre-warmed inventory

A normal POST /orders request never uses or changes pre-warmed pool data. It buys and provisions the submitted domains as a separate order. Only POST /pool/attach can reserve and attach pre-warmed domains.

Pending actions

List open blockers with GET /orders/pending.

Cancellations

Dashboard orders and domains belong to the same org as API purchases and appear in GET /orders and GET /domains. They use stable ord_… and dom_… IDs. Dashboard purchases can have customer_id: null; partner customer tracking is optional. Missing billing facts return costs.total_cents: null. A saved zero-dollar price returns 0. Orders sharing a Stripe subscription return unknown order costs unless they have a saved order quote; the subscription total covers multiple orders. Call POST /orders/{id}/cancel. Wallet orders move to cancel_scheduled immediately. Stripe dashboard orders return 202 with cancellation_pending and saved can_… requests. Poll each returned URL (GET /orders/{id}/cancellations/{cancellation_id}): pending means billing work is running, cancel_scheduled means required billing and Peeker updates succeeded, and failed includes an error. Scheduling does not confirm provider shutdown. The order.cancel_scheduled webhook follows successful completion. A retry reuses the saved cancellation request. Cancelling one domain changes only its managed mailbox seats. Cancelling an order whose Stripe subscription is shared also uses domain targets to preserve sibling orders. Stripe domain selections and whole orders on shared subscriptions support at most 100 domains per request. Wallet selections keep their existing limits. Stripe force cancellation and reactivation are not supported by this endpoint. Registration-only dashboard orders support whole-order renewal cancellation. This also works when their parent subscription is shared: registration renewal stops, while paid expiry dates and sibling inbox subscriptions remain unchanged. Selecting individual domains requires managed inboxes on those domains. Normal finalization is scheduled for the end of the current paid inbox billing period (cancels_at). The selected inboxes stop renewing immediately; cancellation is finalized on that date. Annual domain registration expiry does not extend inbox service. Retrying a scheduled cancellation keeps its accepted date, including cancellations scheduled under the previous 30-day policy. Selected inboxes must share a billing period end; conflicting dates return 409 invalid_request without changing the order.

Late cancellations and Google force cancellation

Microsoft partner-wallet renewals have a 24-hour cancellation grace period from the original renewal timestamp. During grace the wallet is not debited and renewal auto-top-up is not requested. Cancelling during grace queues cancellation immediately. This does not move later monthly renewal dates. Google has no free renewal grace. Any renewal already due is charged before a late cancellation is accepted, even if the scheduled billing job has not run yet. A normal cancellation then ends at the new billing-period boundary. Cancellation still succeeds when the wallet is empty or its credit limit is exhausted: the already-due charge remains owed in the wallet ledger. Payment collection is separate and does not extend the cancellation date. Send { "force": true } to end Google service immediately instead of waiting for the paid period to end. Existing and due renewal charges are retained; this option does not issue a refund. It can also be combined with domains for a Google-only selection. Microsoft force cancellation is not supported. A force request cannot shorten a separate pending cancellation on unselected domains. Immediate cancellation queues the existing service-ending and supplier-notice flows. Acceptance does not confirm that the supplier has disabled its accounts. Supplier messages retain their existing approval requirements. Public costs on the order response are not rewritten when you schedule the cancel.

Retained domains after inbox cancellation

Cancelling inboxes stops renewal without shortening a domain’s paid registration term. Use GET /domains?customer_id=... or GET /domains/{id} to see the retained domain. inbox_status reports cancelled after inbox cancellation completes; registration reports the registration status, expires_at, and auto_renew. The existing domain status is action_required for cancelled inboxes, even when old sequencer stats still show activity. category: connected continues to include domains attached to an order; it does not by itself prove active inbox service. For a partially cancelled order, the same partner and client may submit a new inbox order on the retained domain once its inbox cancellation has finished and the registration has a known, future expiry. Other domains on the original order remain protected. A new request key is needed for the new order; provider eligibility is still checked. Domain registration is not purchased again for an imported inventory domain. Pending cancellations remain blocked.
Last modified on September 28, 2026