Primitive Inbox API
Check inbound email setup and processing readiness
Check inbound email setup and processing readiness
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/primitive-inbox-api"
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: Primitive Inbox API
version: 1.0.0
description: Primitive is email infrastructure for AI agents.
contact:
name: Primitive
url: https://primitive.dev
license:
name: Proprietary
url: https://primitive.dev/terms
x-stability-level: stable
x-deprecation-policy: 'Breaking changes are announced at least 6 months in advance. Deprecated fields carry x-deprecated: true. The current stable version is v1.'
servers:
- url: https://api.primitive.dev/v1
description: Canonical API host (PRIMITIVE_API_BASE_URL). Carries every public API operation.
tags:
- name: Inbox
description: Check inbound email setup and processing readiness
paths:
/inbox/status:
get:
operationId: getInboxStatus
summary: Get inbound inbox readiness
description: Returns one consolidated view of domain verification, webhook/function processing routes, deployed functions, and recent inbound mail. Agents should use this before guiding users through inbound email setup.
tags:
- Inbox
security:
- BearerAuth: []
responses:
'200':
description: Consolidated inbox readiness status
content:
application/json:
schema:
type: object
additionalProperties: false
properties:
ready:
type: boolean
description: True when an active inbound domain and at least one processing route are both ready.
receiving_ready:
type: boolean
description: True when at least one active verified or managed domain can receive mail.
processing_ready:
type: boolean
description: True when at least one receiving-ready domain has an enabled webhook or function route.
summary:
type: string
next_actions:
type: array
items:
type: object
additionalProperties: false
properties:
kind:
type: string
enum:
- add_domain
- verify_domain
- configure_processing
- send_test_email
- fix_failed_functions
message:
type: string
description: Human-readable next step.
command:
type: string
description: Suggested Primitive CLI command when there is an obvious next step.
required:
- kind
- message
domains:
type: array
items:
type: object
additionalProperties: false
properties:
id:
type: string
domain:
type: string
verified:
type: boolean
active:
type: boolean
managed:
type: boolean
receiving_ready:
type: boolean
processing_ready:
type: boolean
processing_route_count:
type: integer
endpoint_count:
type: integer
enabled_endpoint_count:
type: integer
function_endpoint_count:
type: integer
email_count:
type: integer
description: Number of inbound emails received for this domain in the last 30 days.
latest_email_received_at:
type:
- string
- 'null'
format: date-time
description: Most recent inbound email received for this domain in the last 30 days.
status:
type: string
enum:
- ready
- stored_only
- pending_dns
- inactive
required:
- id
- domain
- verified
- active
- managed
- receiving_ready
- processing_ready
- processing_route_count
- endpoint_count
- enabled_endpoint_count
- function_endpoint_count
- email_count
- latest_email_received_at
- status
endpoints:
type: object
additionalProperties: false
properties:
total:
type: integer
enabled:
type: integer
disabled:
type: integer
fallback_enabled:
type: integer
domain_scoped_enabled:
type: integer
http_enabled:
type: integer
function_enabled:
type: integer
required:
- total
- enabled
- disabled
- fallback_enabled
- domain_scoped_enabled
- http_enabled
- function_enabled
functions:
type: object
additionalProperties: false
properties:
total:
type: integer
deployed:
type: integer
pending:
type: integer
failed:
type: integer
required:
- total
- deployed
- pending
- failed
recent_emails:
type: object
description: Inbound email activity from the last 30 days.
additionalProperties: false
properties:
total:
type: integer
description: Number of inbound emails received in the last 30 days.
latest_received_at:
type:
- string
- 'null'
format: date-time
description: Most recent inbound email received in the last 30 days.
required:
- total
- latest_received_at
required:
- ready
- receiving_ready
- processing_ready
- summary
- next_actions
- domains
- endpoints
- functions
- recent_emails
headers:
ratelimit-limit:
description: Maximum number of requests allowed in the current window.
schema:
type: integer
minimum: 1
example: 120
ratelimit-remaining:
description: Remaining requests in the current window.
schema:
type: integer
minimum: 0
example: 118
ratelimit-reset:
description: Unix timestamp (seconds) when the current window resets.
schema:
type: integer
example: 1700000060
ratelimit-policy:
description: Rate-limit policy in `limit;w=seconds` format, e.g. `120;w=60`.
schema:
type: string
example: 120;w=60
'401':
$ref: '#/components/responses/Unauthorized'
description: Invalid or missing API key
'429':
$ref: '#/components/responses/RateLimited'
description: Rate limit exceeded
components:
schemas:
ErrorResponse:
type: object
properties:
success:
type: boolean
const: false
error:
type: object
properties:
code:
type: string
enum:
- unauthorized
- forbidden
- not_found
- validation_error
- rate_limit_exceeded
- internal_error
- conflict
- mx_conflict
- outbound_disabled
- cannot_send_from_domain
- recipient_not_allowed
- outbound_key_missing
- outbound_unreachable
- outbound_key_invalid
- outbound_capacity_exhausted
- outbound_response_malformed
- outbound_relay_failed
- discard_not_enabled
- inbound_not_repliable
- search_timeout
- authorization_pending
- slow_down
- access_denied
- expired_token
- invalid_device_code
- invalid_signup_code
- invalid_signup_token
- invalid_verification_code
- email_delivery_failed
- clerk_signup_failed
- no_orgs_for_user
- org_not_accessible
- feature_disabled
- memory_conflict
- developer_usage_credit_exhausted
- no_payout_address
- ownership_proof_failed
- payment_verification_failed
- payment_declined
- challenge_expired
- settlement_failed
- template_not_installable
- scaffold_only
- invalid_variables
- unknown_secrets
- missing_secrets
- no_inbound_domain
- domain_cannot_send
- address_taken
- route_cap_reached
- name_exhausted
message:
type: string
details:
type: object
description: 'Optional structured data that callers can inspect to recover
from the error. The fields present depend on `code`. Additional
keys may be added over time without a major-version bump.
'
additionalProperties: true
properties:
mx_conflict:
type: object
description: Present when `code == mx_conflict`.
required:
- provider_name
- suggested_subdomain
properties:
provider_name:
type: string
description: Human-readable name of the detected mailbox provider (e.g. "Google Workspace").
suggested_subdomain:
type: string
description: Subdomain to try instead (e.g. "mail" for `mail.example.com`).
required_entitlements:
type: array
items:
type: string
description: Entitlements that would allow a denied send when no recipient-scope gate was granted.
sent_email_id:
type: string
description: ID of the persisted sent-email attempt associated with the error.
content_hash:
type: string
description: Content hash of the original request on idempotency cache-hit errors.
client_idempotency_key:
type: string
description: Effective idempotency key associated with the original request.
gates:
type: array
items:
$ref: '#/components/schemas/GateDenial'
description: Structured per-gate denial detail for recipient-scope send-mail failures.
request_id:
type: string
description: Server-issued request identifier for support and tracing.
required:
- code
- message
required:
- success
- error
GateDenial:
type: object
properties:
name:
type: string
enum:
- send_to_confirmed_domains
- send_to_known_addresses
description: Public recipient-scope gate name that denied the send.
reason:
type: string
enum:
- domain_not_confirmed
- recipient_unauthenticated
- recipient_not_known
description: Stable machine-readable denial reason.
message:
type: string
description: Human-readable explanation of the gate denial.
subject:
type: string
description: Domain or address the gate evaluated.
fix:
$ref: '#/components/schemas/GateFix'
docs_url:
type: string
description: Public docs URL with more context.
required:
- name
- reason
- message
- subject
GateFix:
type: object
properties:
action:
type: string
enum:
- confirm_domain
- sender_must_fix_authentication
- wait_for_inbound
description: Suggested next action for the caller.
subject:
type: string
description: Entity the action applies to.
required:
- action
- subject
responses:
Unauthorized:
description: Invalid or missing API key
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
success: false
error:
code: unauthorized
message: Invalid or missing API key
RateLimited:
description: Rate limit exceeded
headers:
Retry-After:
schema:
type: integer
description: Seconds to wait before retrying
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
success: false
error:
code: rate_limit_exceeded
message: Rate limit exceeded
securitySchemes:
BearerAuth:
type: http
scheme: bearer
description: 'API key with `prim_` prefix or OAuth access token with `prim_oat_` prefix: `Authorization: Bearer <token>`. Access is governed by the caller''s organization role (`owner`, `admin`, or `member`): API keys always act at `member` level regardless of who created them, and OAuth access tokens act with the authorizing user''s current organization role, resolved per request. Every operation in this spec is available to organization members; billing and organization administration are owner/admin actions performed in the dashboard and are not part of this API.'
DownloadToken:
type: apiKey
in: query
name: token
description: Signed download token provided in webhook payloads