Use an organization API key in Authorization: Bearer <key>. Every result is scoped to that key's workspace. These read endpoints use the same inventory and date-range projections as the customer Infrastructure views.
| Endpoint | Result |
|---|---|
GET /api/v1/infrastructure/domains | Domain inventory, assignment and use counts, capacity, daily sends, and available domain health. |
GET /api/v1/infrastructure/mailboxes | Mailbox inventory, lifecycle and warming state, capacity, assignment, and recent activity. Each item's ramp_up gives its stage (first_week, stepping_up, at_full_limit, held, reduced or fixed_limit), hold reason, full limit and progress; ramp_up_stage_counts counts the listed mailboxes by stage when any is automatic. Maintenance credentials are never included. |
GET /api/v1/infrastructure/distribution | Campaign mailbox assignments and recently used distribution. |
GET /api/v1/infrastructure/capacity | Workspace capacity as shown in Infra › Capacity: daily_capacity today, subscribed_per_day (null when not recorded), sent_per_day and unused_per_day over the last 7 complete UTC days with unused_reason, loaded_leads (every pending lead in active, started campaigns), which splits into loaded_leads_sendable (its email check is deliverable, so it can start; shown as Loaded leads in Infra › Capacity), loaded_leads_unsendable (the email check blocked it, or it can never send: no email address, or a deleted lead) and loaded_leads_awaiting_email_check, which normally add up to loaded_leads, new_leads_per_sending_day and lead_runway (state, sending_days, lasts_until; it counts only loaded_leads_sendable), ramp_up stage counts for sending mailboxes when any is automatic, warm_up for a new workspace that has never sent campaign email (day of days, complete, ends_on (the first day after warm-up), sending_starts_on, mailbox_count (projected senders), backup_mailbox_count, floor_daily_limit, ceiling_daily_limit, daily_capacity_from_sending_start, reaches_subscribed_on, ramp_up_finishes_on or still_growing_after; unused_reason is then warm_up), and days: 14 history days and today plus horizon_days (21 default, or 42) with daily_capacity, sent or estimated scheduled. Projected capacity follows the ramp-up projection; during warm-up it is 0 until sending_starts_on and then assumes every prepared automatic mailbox sends on weekdays. Scheduled sends are an estimate from each campaign's last 7 days and its sendable loaded leads. Dates are UTC days. |
GET /api/v1/infrastructure/capacity-allocation | Capacity allocation as shown in Infra › Allocation. Workspace totals: in_campaigns_per_day, usable_per_day (in campaigns plus Available), available_per_day, reserve_per_day and reserve_target_per_day (equal to subscribed_per_day; null without a subscription), labelled_backup_per_day, recovering_per_day, warm_up_per_day and delivered (last full Monday–Friday week: week_of, sent_per_day, sending_days, percent_of_subscribed). campaigns lists draft, submitted, active, ending and paused campaigns that hold domains or have leads, with capacity_per_day, domain_count, sent_per_day_last_5_days, leads (total, not_yet, started, completed; not_yet counts every lead not yet started and splits into not_yet_sendable (its email check is deliverable, so it can start; shown as New in Infra › Allocation), not_yet_unsendable (the email check blocked it, or it can never send: no email address, or a deleted lead) and not_yet_awaiting_email_check, which normally add up to not_yet; they are read moments apart, so a send in between can briefly make them differ), completes_on from the campaign send timeline with completion (projected, no_leads (no lead may still send: none loaded, all finished, or the rest unsendable), no_capacity, beyond_horizon or unknown) and completion_failed (true when projecting this campaign's date failed, so unknown means not read rather than not known; read again to retry), plannable (overlap on and provider routing set up) and shared_domains. days runs from history_from (optional query parameter, YYYY-MM-DD; default 14 days back, at most 180) through the projection, with each campaign's capacity and sends, earlier campaigns, and Available, Reserve, Recovering and warm-up capacity. History capacity starts with daily capacity history; earlier days carry sends only. needs_attention lists suggestions; nothing moves automatically. Each item has a code, a severity (short, warning or info), an optional campaign_id, a title and a text. runs_out_of_new_leads (severity warning) appears when the campaign send timeline starts a sending campaign's last new lead today or within its next 5 sending days; its new_leads_run_out object gives runs_out_on, then_percent_of_capacity and then_sending_days (its mailboxes then send only follow-ups, at about that share of the campaign's current capacity_per_day, for that many of its sending days; both are 0 when no follow-ups remain) and awaiting_email_check. runs_out_on is a day in the campaign's time zone, as the send timeline counts it; it is not reported while a new lead that could start is still unstarted at the end of the projection. can_apply_plans is always false and labelling_dry_run is always null for an API key. Dates are UTC days. |
POST /api/v1/infrastructure/capacity-plans/preview | Preview a capacity plan without changing anything. Body: campaigns (up to 20: campaign_id, unit pct of usable capacity, sends_per_day or domains to add (a whole number up to 500), value, use_reserve) and returns (up to 20 completed, ended or paused campaigns, at either overlap setting: campaign_id, started_leads keep_on_current or reassign, optional domain_count), limited to 64 KiB. The result lists the whole domains each campaign would gain, from Available or the reserve, with per-target capacity, before_per_day counted as Allocation counts it (a shared domain once, under the campaign that is sending), completion before and after, and shortfall_reason/shortfall_text when it falls short; returns list the domains given back. A domain shared by two campaigns in one plan can be returned only once. A return is refused while the campaign still has assignments on inactive mailboxes, and reassign is refused when no domain the campaign keeps is in every sending pool the started leads use; any refused return makes the whole plan not applicable. A plan never takes domains from a running campaign, never splits a domain and never creates sharing. Only campaigns with overlap on and provider routing set up can gain domains. applicable is always false for an API key: Lightmeter staff apply plans in the UI or through MCP. |
GET /api/v1/infrastructure/campaign-assignments | Bounded active Campaign mailbox assignments with campaign, mailbox, and domain references. domain_campaign_visible distinguishes campaigns included in the domain list from historical campaigns still present in mailbox and distribution lists. Defaults to 100 items; use limit from 1 to 100 and page.next_cursor to continue. |
GET /api/v1/infrastructure/onboarding-build-status | Aggregate domain and mailbox build progress for the workspace. Returns 204 when there is no current onboarding build. |
GET /api/v1/infrastructure/ramp-up/domains | Customer-visible domain and mailbox health, ramp-up progress, and allocation policy evidence. Optional include_health=false and include_mailboxes=false reduce work and response size. |
GET /api/v1/infrastructure/ramp-up/domains/{domain_uuid}/mailboxes | Bounded ramp-up mailbox rows for one active workspace domain. Defaults to 100 rows; use limit (1 to 100) and page.next_cursor. Set compact=true to omit large campaign arrays and use campaign-assignment pages for those relationships. |
GET /api/v1/infrastructure/ramp-up/domains/{domain_uuid}/mail-server-sent-counts | Mail-server sent counts for one workspace domain and date range. |
GET /api/v1/infrastructure/ramp-up/mailboxes/{mailbox_id} | Reputation, volume, projection, and ramp-up history for one workspace mailbox. ramp_up adds its stage, effective, next-step and full limits, earned days, last and next check, and the latest check results (checks: Infra Health against the floor, campaign email sent, assignment to a running campaign, Content Health, able to send; null means not checked). |
GET /api/v1/infrastructure/ramp-up/mailboxes/{mailbox_id}/send-log | Cursor-paged campaign send log for one workspace mailbox. Warming and other staff send types are unavailable. |
POST /api/v1/infrastructure/domains/export | Stream customer-visible domains as CSV. Optional JSON body: {"domain_uuids":["..."]}, limited to 64 KiB. Omit the selection to export all customer-visible domains. |
POST /api/v1/infrastructure/mailboxes/export | Stream customer-visible mailboxes as CSV. Optional JSON body: {"mailbox_uuids":["..."]}, limited to 64 KiB. Omit the selection to export all customer-visible mailboxes. Login credentials cannot be exported through an organization API key. |
Omit query parameters for the rolling 5d window, or set window=24h. For a custom inclusive UTC date range, provide both start_date and end_date in YYYY-MM-DD format. Custom ranges are limited to 90 days. Invalid ranges return 400.
Example: GET /api/v1/infrastructure/domains?start_date=2026-09-01&end_date=2026-09-29.
The response retains the browser's window, date_range, summary, and items fields. Domain responses also include current capacity and daily-send fields. These are workspace inventory views and do not include staff provisioning or login credentials.
Domain, mailbox, distribution, ramp-up domain, and domain mail-server sent-count lists accept limit from 1 to 100. Pass the returned page.next_cursor as cursor, with the same limit, workspace, date controls, and ramp-up options, until no next cursor remains. An omitted limit preserves the existing full response. Opaque cursors are limited to 1024 characters to bound untrusted input; return the server-issued value unchanged. Invalid cursors, or cursors used with another workspace or different filters, return 400; an inventory or projected result that changes during traversal returns 409 and requires a restart from the first page.
Domain and mailbox pages return tenant-scoped items. Their page.summary_scope=page means summary covers only returned items; domain daily-send and capacity metadata remain workspace-wide. Set compact=true on domain or mailbox lists to omit potentially large nested campaign arrays, then traverse /infrastructure/campaign-assignments for those relationships. Domain campaign references include only assignments with domain_campaign_visible=true; mailbox references include the other returned historical assignments too. Set compact=true on distribution to retain its counts while omitting nested domain and mailbox arrays; the same assignment pages carry the members. Distribution, ramp-up, and sent-count pages retain workspace-wide summary fields and report page.summary_scope=workspace. Pagination bounds the returned data for grouped results, but processing time may still grow with workspace size.
Cursors are tied to the first page's time, active workspace, filters, and compact mode. Inventory membership changes trigger a restart; grouped projections also restart when their contents change. Results are not a frozen database snapshot across requests. For a ramp-up domain whose nested mailbox rows exceed 128 KiB even at limit=1, request include_mailboxes=false, then traverse /infrastructure/ramp-up/domains/{domain_uuid}/mailboxes with compact=true as needed. The assignment pages restore omitted campaign references. Individual mailbox reputation, volume, projection, and capped 100-entry history remain available at the separate mailbox-detail endpoint.
CSV exports accept the same date controls. Selected UUIDs are deduplicated; an empty selection on the public API exports all visible rows. Values that could be interpreted as spreadsheet formulas are neutralized in the CSV. HTTP downloads are staged before delivery and limited to 128 MiB. OAuth MCP export tools require 1 to 500 selected UUIDs and return CSV text up to 128 KiB. OAuth-only clients can traverse inventory pages and export selected UUIDs in batches. If one row's campaign names exceed the MCP limit, use compact=true on the export: the campaigns cell is blank while assignment status is preserved; campaign names and relationships remain available through campaign-assignment pages. A single all-inventory CSV export requires the public API and an organization API key.
The send log accepts the date controls above, or a pair of RFC3339 start_at and end_at timestamps with at most microsecond precision and a range of at most 90 days. Do not combine timestamp and date/window controls. Optional filters are time_zone (IANA name, default UTC), recipient_classification (G, M, S, O, or unknown), campaign_id, and order (asc or desc). Use limit from 1 to 100 and the returned next_cursor for the next page with unchanged filters. A changed snapshot returns 409 and should be restarted from the first page.
A walk-in request visits the root of a sending domain, such as https://sending.example/. It redirects to the workspace's configured website. It identifies neither an email recipient nor the campaign that caused the visit. Personalized URL clicks have separate metrics.
| Endpoint | Contract |
|---|---|
GET /api/v1/infrastructure/domains/{domain_uuid}/walkin | Read one owned domain's destination, participation and UTM campaign label, including its effective destination and readiness. |
PATCH /api/v1/infrastructure/domains/{domain_uuid}/walkin | Update any of use_default, redirect_url, enabled and utm_campaign. Supply at least one field. use_default:true follows the workspace default destination; redirect_url alone selects Custom. Requires the settings-management grant; the web app and MCP require a workspace Admin, Owner or authorized staff member. |
PATCH /api/v1/infrastructure/domains/walkin | Atomically update participation and/or destination for 1–200 active owned domains with {"domain_uuids":["uuid"],"enabled":true,"use_default":false,"redirect_url":"https://www.example.com/"}. Supply at least one of enabled, use_default and redirect_url; null values and other fields, including utm_campaign, return 400. Each domain follows the single-domain rules: redirect_url alone selects Custom, use_default:true follows the workspace default (400 when none is set or with a conflicting URL), and use_default:false keeps each domain's current URL as custom. Requires the same settings-management permission. Duplicate UUIDs are applied once; any invalid, inactive or inaccessible domain, or any resulting invalid destination (such as a URL on a selected sending domain), rejects the entire selection and changes nothing. A destination that one selected domain rejects, such as a URL on that sending domain, returns 400 naming that domain, with its UUID in details.domain_uuid. Returns {"domains":[{"domain_uuid":"uuid","enabled":true,"use_default":false,"redirect_url":"https://www.example.com/","changed":true}]} only after commit. Preserves analytics labels and destinations already issued in personalized URLs. Enabling requires workspace tracking; disabling and destination changes remain available while it is paused. Domain participation and destinations affect all mailboxes on each domain, and do not imply routing readiness. |
GET /api/v1/reports/walkin | Read aggregate observed requests and classification coverage for the workspace. Accepts the date controls above, optional domain_uuid and include_retired=true. |
The domain response contains domain_uuid, domain, redirect_url, enabled, utm_campaign, effective_redirect_url, ready, can_update, workspace_tracking_enabled, enable_utm_source, default_redirect_url and use_default. Updates also return changed; saving unchanged values is safe. A missing or inaccessible domain returns the same 404 response. An invalid effective configuration returns 400. Enabling domain tracking while workspace tracking is disabled returns 409. A destination must be an absolute HTTP or HTTPS URL without embedded credentials, control characters or a redirect back to the sending domain. An unconfigured or invalid saved destination has a null preview.
Example request body: {"redirect_url":"https://www.example.com/landing","enabled":true,"utm_campaign":"Autumn launch"}. The UTM campaign label is text for the destination website's existing analytics; it is not a campaign ID. Domain participation controls walk-in tagging and tracking eligibility. Workspace tracking is a separate, initially disabled setting at PATCH /api/v1/settings/general/walkin-tracking. The domain response includes that workspace state and source preference. Set use_default:true to follow the current workspace destination; use_default:false freezes the current URL as custom. Supplying redirect_url alone selects Custom. A conflicting URL with use_default:true is rejected.
Disabling workspace tracking keeps redirects working. Configured destinations and UTM choices take priority over visitor query parameters. Destination changes do not rewrite destinations already issued in personalized URLs. Root navigation uses an ordinary temporary HTTP redirect without a JavaScript interstitial; asynchronous classification never waits on the destination response. Navigation depends on application/database availability.
The report contains date_range, tracking_status, summary, domains, series and campaign_associations. Each count group contains high_confidence_navigation_count (retained navigation estimate), optimistic_navigation_count (inclusive estimate plus positively evidenced uncertain visits), observed_requests, estimated_navigation_count, automated_requests, unknown_requests and non_navigation_requests. These count requests, not unique people. Normal reports show visits with a grey bracketed optimistic total only when it is larger. Existing diagnostic fields and nullable estimate behavior remain compatible. HEAD and prefetch requests do not count as navigations.
high_confidence_navigation_count counts browser navigations that pass the same bot filtering as campaign clicks: a current browser on an ordinary ISP or business network, or a recognized relay service such as Apple Private Relay, with no bot detected. Visits through other VPN, proxy and hosting networks do not count, because nearly all walk-in traffic from them is automated. Requests that match patterns of automated scanning count as automated requests. A walk-in counts in neither value when its domain had not yet sent campaign email before the visit, the browser is long outdated, or the request shows other signs of automation. A visitor on an ordinary network or recognized relay service who opens several of the workspace's walk-in domains can count on each. Counts for the last 24 hours are provisional and can move from navigation to automated. estimated_navigation_count is a bot-filtered navigation estimate, not verified humans. It is null when unknown observations exist and no qualifying estimate is available. Pending, unavailable and unsupported classification remains unknown; do not convert null to zero. A successful empty report means no recorded data in that range. An API failure must remain an error.
tracking_status distinguishes paused, unavailable, active and incomplete. Readiness describes routing and tracking prerequisites, not detector accuracy. Default domain performance rows include active participating domains with zero recorded requests and current domains with historical requests. Domains no longer active in this workspace require the retired-domain view. The explicit retired-domain view can include facts captured for this workspace after the new tracking started. Reassignment never transfers another workspace's history. Historical data from the retired collector is not imported.
Campaign associations use current_campaign_at_visit only where one current campaign owned the domain at observation; otherwise their basis is unassigned. A late visitor may have seen an earlier campaign, so the association does not establish causation or recipient identity. No human-recognition accuracy, attribution percentage or deliverability guarantee is implied.
MCP exposes these same contracts through workspace_infrastructure_domain_walkin_get, workspace_infrastructure_domain_walkin_update, workspace_infrastructure_domains_walkin_update and workspace_walkin_report_get. The bulk tool accepts domain_uuids and any of enabled, use_default and redirect_url directly. Domain tools accept domain_uuid; updates put the public API body in payload. Report arguments use the same date, domain and retired-domain filters. Workspace tracking/source-tag updates use workspace_walkin_tracking_update. All resolve an accessible workspace and retain the same permissions.
OAuth clients can use workspace_infrastructure_domains_list, workspace_infrastructure_mailboxes_list, workspace_infrastructure_distribution_list, workspace_infrastructure_campaign_assignments_list, workspace_infrastructure_onboarding_build_status_get, workspace_infrastructure_ramp_up_domains_list, workspace_infrastructure_ramp_up_domain_mailboxes_list, workspace_infrastructure_domain_mail_server_sent_counts_get, workspace_infrastructure_ramp_up_mailbox_get, workspace_infrastructure_mailbox_send_log_list, workspace_infrastructure_domains_export, and workspace_infrastructure_mailboxes_export. They accept the same applicable filters and resolve an accessible workspace_id before running the same public service contract. Every infrastructure MCP structured result, including domain mail-server sent counts, has a complete 128 KiB limit. For larger lists, start with limit=50, follow next_cursor, and reduce the limit or use compact=true plus assignment pages if one item is too large. A paged send log has its separate snapshot cursor contract. Export selected inventory UUIDs in bounded MCP batches; a single all-inventory CSV export still requires the public API and an organization API key. capacity_allocation_get and capacity_plan_preview read and preview capacity allocation like the API above. Capacity plans are available in every workspace; there is no per-workspace switch.