Skip to main content
The standard partner flow starts with a sandbox key (pk_test_…), checks whether the domains are usable, imports any domains the customer already owns, places the order, and listens for webhooks. Sandbox orders complete quickly and never bill.

Real partner smoke test

Use this three-call sequence first when you are wiring the API from your own app:
  1. POST /domains/availability - confirm the domains are valid and usable.
  2. POST /domains/import - attach customer-owned domains to your partner inventory.
  3. POST /orders - create or reuse the customer by email and start provisioning.
That sequence is what Peeker’s Partner API E2E suite runs before it exercises the rest of the endpoint matrix. Create bundles when you want reusable order templates; for the first smoke test, a custom order with google_licenses or microsoft_licenses is usually faster.

Steps in detail

1. Create your bundles

A bundle is a saved order size. Send name and monthly_sending_volume; optionally add google_percent and microsoft_percent. Bundles default to weekday-only sending (send_on_weekends: false) and 2 Google inboxes/domain. Use the returned bun_… ID on orders. The response also tells you how many Google and Microsoft domains the customer must pick.
cURL
curl -X POST "https://api.peeker.ai/partner/v1/bundles" \
  -H "Authorization: Bearer pk_test_<your-key>" \
  -H "Content-Type: application/json" \
  --data '
{
  "name": "Starter - 25k emails/month",
  "monthly_sending_volume": 25000,
  "send_on_weekends": false,
  "google_inboxes_per_domain": 2
}'
201 Created
{
	"data": {
		"id": "bun_01HZX0BU1A2B3C4D5E6F7G8H",
		"name": "Starter - 25k emails/month",
		"monthly_sending_volume": 25000,
		"google_percent": null,
		"microsoft_percent": null,
		"send_on_weekends": false,
		"google_inboxes_per_domain": 2,
		"effective": {
			"google_percent": 50,
			"microsoft_percent": 50
		},
		"required_domains": {
			"google": 15,
			"microsoft": 4,
			"total": 19
		},
		"status": "active",
		"created_at": "2026-05-08T12:00:00Z"
	}
}
Generate domain candidates yourself, or let the customer search. Send up to 50 per call. Available rows include price, renewal price, and usable_for; unavailable rows include a reason.
cURL
curl -X POST "https://api.peeker.ai/partner/v1/domains/availability" \
  -H "Authorization: Bearer pk_test_<your-key>" \
  -H "Content-Type: application/json" \
  --data '
{
  "domains": [
    "acme-mail.com",
    "team-acme.com"
  ]
}'
200 OK
{
	"data": {
		"domains": [
			{
				"domain": "acme-mail.com",
				"available": true,
				"price_cents": 1300,
				"renewal_price_cents": 1500,
				"currency": "usd",
				"usable_for": ["google", "microsoft"]
			},
			{
				"domain": "team-acme.com",
				"available": true,
				"price_cents": 1300,
				"renewal_price_cents": 1500,
				"currency": "usd",
				"usable_for": ["google"]
			}
		]
	}
}
Microsoft domains must include "microsoft" in usable_for. Match the bundle’s required_domains.microsoft count before checkout. Filter or flag Google-only rows when the customer still needs Microsoft-capable domains.
POST /orders provisions everything in one call. You pass:
  • bundle_id - the bundle from step 1; resolves the license mix.
  • user - an email to create/reuse, or an existing usr_… user ID.
  • sequencer - Smartlead routing plus the login credentials Peeker uses internally for provider submission.
  • forwarding_url - the default redirect for every domain in the order.
  • domains - the available domains you picked, selected to satisfy the bundle’s Microsoft split.
  • personas - names and required profile_picture_url keys used to generate inbox names.
Smartlead orders require both sequencer.login_email and sequencer.login_password; a Smartlead client ID or API key alone is not enough for Peeker to submit the provider work.Re-sending the exact same body returns the original order - no second charge, no duplicate provisioning. Orders dedupe for 24 hours.
cURL
curl -X POST "https://api.peeker.ai/partner/v1/orders" \
  -H "Authorization: Bearer pk_test_<your-key>" \
  -H "Content-Type: application/json" \
  --data '
{
  "user": "alex@acme.com",
  "bundle_id": "bun_01HZX0BU…",
  "sequencer": {
    "provider": "smartlead",
    "client_id": 366903,
    "login_email": "peeker@yourcompany.com",
    "login_password": "<your-dedicated-login>"
  },
  "forwarding_url": "https://acme.com",
  "domains": [
    "acme-mail.com",
    "team-acme.com"
  ],
  "personas": [
    {
      "first_name": "Alex",
      "last_name": "Rivera",
      "profile_picture_url": ""
    },
    {
      "first_name": "Sam",
      "last_name": "Lee",
      "profile_picture_url": ""
    }
  ]
}'
200 OK
{
	"data": {
		"id": "ord_01HZX0OR1A2B3C4D5E6F7G8H",
		"user_id": "usr_01HZX0C6Z3K4M5N6P7Q8R9S0",
		"email": "alex@acme.com",
		"bundle_id": "bun_01HZX0BU…",
		"status": "in_progress",
		"domain_count": 2,
		"costs": {
			"total_cents": 6800,
			"currency": "usd"
		},
		"created_at": "2026-05-08T12:00:00Z"
	}
}
Configure your endpoint in the Partner portal → Webhooks before placing the order. Events fire in this sequence:
order.in_progress  →  domain.connected (one per domain)  →  order.completed
The order.completed payload is the full order. Verify the signature before trusting any payload.
Webhook · order.completed
{
	"id": "evt_01HZX0EV2A2B3C4D5E6F7G8H",
	"type": "order.completed",
	"created_at": "2026-05-08T12:14:33Z",
	"data": {
		"id": "ord_01HZX0OR1A2B3C4D5E6F7G8H",
		"status": "completed",
		"domain_count": 2
	}
}
Live orders return order.in_progress immediately. Google and Microsoft orders typically complete within 24 hours - Google can take up to 48 hours when domains need to run through Peeker’s recovery flow. Sandbox completes in seconds.

What’s next

Importing domains & ordering

The separate flow for domains the customer already owns - import, not availability check.

Buying domains & ordering

More detail on the registrar-sourced order path.

Best practices

Rate limits, errors, paging, idempotency, pending actions.
Last modified on June 29, 2026