---
title: "Provision a complete agent identity in one call"
method: POST
path: "/api/agents/provision"
tags: ["Domains"]
---

# Provision a complete agent identity in one call

`POST /api/agents/provision`

## Request

- Base URL: `https://domani.run`
- URL: `https://domani.run/api/agents/provision`
- Auth: HTTP bearer

Gives an AI agent a complete internet identity in a single request: buys the domain (if not already owned), sets up email DNS, creates a mailbox, and optionally registers an authenticated webhook for inbound email and domain events. `webhook_headers` accepts only `Authorization` and `X-API-Key`; values are encrypted at rest and never returned. Repeating the same domain, mailbox slug, and webhook URL reuses those resources.

Every webhook input is validated before a domain purchase or charge. The domain purchase is the only step that can charge and the only hard prerequisite - if it fails, the whole call fails (402 for payment, 409 if taken by another account). Email setup, mailbox creation, and webhook registration are best-effort: transient issues (e.g. DNS still propagating) are returned in `warnings` rather than failing the call, so the agent always gets its domain.

Payment works exactly like POST /api/domains/buy (card, marketplace balance, or USDC via the `PAYMENT-SIGNATURE` header / two-step flow).

## Headers

- `PAYMENT-SIGNATURE` string

## Request body

- object
  - `domain` string, required: Domain to give the agent. Bought if not already owned.
  - `slug` string: Mailbox local part (hi@domain). Default 'hi'.
  - `name` string: Display name for outbound email.
  - `webhook_url` string, uri: Optional HTTPS URL to receive inbound email + domain events.
  - `webhook_headers` object: Optional delivery authentication. Values are encrypted at rest and never returned; responses expose header_names only.
    - `Authorization` string
    - `X-API-Key` string
  - `webhook_events` string[]: Webhook event types. Defaults to email.received/delivered/bounced.
  - `payment_method` 'card' | 'usdc' | 'balance': How to pay for the domain.
  - `payment_tx` string: USDC tx hash (two-step flow).
  - `payment_chain` 'base' | 'ethereum'
  - `years` integer
  - `max_price` number: Ceiling in USD for the domain charge. If the real price exceeds it, the request fails with 400 PRICE_ABOVE_MAX and nothing is charged. The error's `price` field is the total to accept; confirm it with the user before retrying with that max_price.

## Response `200`

Agent provisioned (domain already owned)

- ProvisionAgentResult
  - `domain` string, required
  - `domain_status` 'registered' | 'owned', required
  - `mailbox` object, nullable, required
    - `address` string, required
    - `status` 'created' | 'existing', required
  - `webhook` object, nullable, required
    - `id` string, required
    - `url` string, required
    - `secret` string: HMAC signing secret, returned only when the webhook is first created.
    - `header_names` string[], required: Configured delivery authentication header names; values are never returned.
  - `warnings` string[], required
  - `hint` string, required
  - `next_steps` string[], required

## Other responses

- `201`: Agent provisioned (domain registered)
- `402`: Payment required for the domain
- `409`: Domain is registered to another account

---

[API](https://skmtc.dev/domani/apis/domani-run-api.md) · [All operations](https://skmtc.dev/domani/apis/domani-run-api/llms.txt) · [OpenAPI document](https://skmtc.dev/domani/apis/domani-run-api/revisions/7679f8159533?raw)
