Skip to content

Agent Onboarding

Fresh 🌱

AgentMail REST API reference for Agent Onboarding. Base URL https://api.agentmail.to/v0. Authenticate with Authorization: Bearer <API_KEY>.

Sign Up

POST https://api.agentmail.to/v0/agent/sign-up Content-Type: application/json

Create a new agent organization with an inbox and API key. This endpoint is for signing up for the first time. If you've already signed up, you're all set — just use your existing API key.

A 6-digit OTP is sent to the human's email for verification.

This endpoint is idempotent. Calling it again with the same human_email will rotate the API key and resend the OTP if expired.

The returned API key has limited permissions until the organization is verified via the verify endpoint.

CLI:

bash
agentmail agent sign-up --human-email user@example.com --username my-agent

OpenAPI Specification

yaml
openapi: 3.1.0
info:
  title: api
  version: 1.0.0
paths:
  /v0/agent/sign-up:
    post:
      operationId: sign-up
      summary: Sign Up
      description: >-
        Create a new agent organization with an inbox and API key. This endpoint
        is for signing up for the first time. If you've already signed up,
        you're all set — just use your existing API key.

        A 6-digit OTP is sent to the human's email for verification.

        This endpoint is idempotent. Calling it again with the same
        `human_email` will rotate the API key and resend the OTP if expired.

        The returned API key has limited permissions until the organization is
        verified via the verify endpoint.

        **CLI:**

        ```bash

        agentmail agent sign-up --human-email user@example.com --username
        my-agent

        ```
      tags:
        - subpackage_agent
      responses:
        '200':
          description: Response with status 200
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/type_agent:AgentSignupResponse'
        '400':
          description: Error response with status 400
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/type_:ValidationErrorResponse'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/type_agent:AgentSignupRequest'
servers:
  - url: https://api.agentmail.to
    description: prod
  - url: https://x402.api.agentmail.to
    description: prod-x402
  - url: https://mpp.api.agentmail.to
    description: prod-mpp
  - url: https://api.agentmail.eu
    description: eu-prod
components:
  schemas:
    type_agent:AgentSignupRequest:
      type: object
      properties:
        human_email:
          type: string
          description: >-
            Email address of the human who owns the agent. A 6-digit OTP will be
            sent to this address.
        username:
          type: string
          description: >-
            Username for the auto-created inbox (e.g. "my-agent" creates
            my-agent@agentmail.to).
        source:
          type: string
          description: >-
            The SDK, framework, or platform issuing this sign-up (e.g.
            `agentmail-python`, `agentmail-cli`, `agentmail-mcp`).

            Identifies the caller — answers "who is signing up".

            Max 2048 characters.
        referrer:
          type: string
          description: >-
            The channel that drove this sign-up — where the agent or its
            developer discovered AgentMail

            (e.g. `agent.email`, a partner URL, a campaign tag). Answers "where
            did this sign-up come from".

            Max 2048 characters.
      required:
        - human_email
        - username
      description: Request body to sign up an agent.
      title: AgentSignupRequest
    type_agent:AgentSignupResponse:
      type: object
      properties:
        organization_id:
          type: string
          description: ID of the created organization.
        inbox_id:
          type: string
          description: ID of the auto-created inbox.
        api_key:
          type: string
          description: >-
            API key for authenticating subsequent requests. Store this securely,
            it cannot be retrieved again.
      required:
        - organization_id
        - inbox_id
        - api_key
      description: Response after successful agent sign-up.
      title: AgentSignupResponse
    type_:ErrorName:
      type: string
      description: Name of error.
      title: ErrorName
    type_:ValidationErrorResponse:
      type: object
      properties:
        name:
          $ref: '#/components/schemas/type_:ErrorName'
        errors:
          description: Validation errors.
      required:
        - name
        - errors
      title: ValidationErrorResponse

Examples

Request

json
{
  "human_email": "human_email",
  "username": "username"
}

Response

json
{
  "organization_id": "organization_id",
  "inbox_id": "inbox_id",
  "api_key": "api_key"
}

SDK Code

typescript
import { AgentMailClient } from "agentmail";

async function main() {
    const client = new AgentMailClient();
    await client.agent.signUp({
        humanEmail: "human_email",
        username: "username",
    });
}
main();
python
from agentmail import AgentMail

client = AgentMail()

client.agent.sign_up(
    human_email="human_email",
    username="username",
)
go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.agentmail.to/v0/agent/sign-up"

	payload := strings.NewReader("{\n  \"human_email\": \"human_email\",\n  \"username\": \"username\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
ruby
require 'uri'
require 'net/http'

url = URI("https://api.agentmail.to/v0/agent/sign-up")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n  \"human_email\": \"human_email\",\n  \"username\": \"username\"\n}"

response = http.request(request)
puts response.read_body
java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.agentmail.to/v0/agent/sign-up")
  .header("Content-Type", "application/json")
  .body("{\n  \"human_email\": \"human_email\",\n  \"username\": \"username\"\n}")
  .asString();
php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.agentmail.to/v0/agent/sign-up', [
  'body' => '{
  "human_email": "human_email",
  "username": "username"
}',
  'headers' => [
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
csharp
using RestSharp;

var client = new RestClient("https://api.agentmail.to/v0/agent/sign-up");
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"human_email\": \"human_email\",\n  \"username\": \"username\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
swift
import Foundation

let headers = ["Content-Type": "application/json"]
let parameters = [
  "human_email": "human_email",
  "username": "username"
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.agentmail.to/v0/agent/sign-up")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()

Verify

POST https://api.agentmail.to/v0/agent/verify Content-Type: application/json

Verify an agent organization using the 6-digit OTP sent to the human's email during sign-up.

On success, the organization is upgraded from agent_unverified to agent_verified, the send allowlist is removed, and free plan entitlements are applied.

The OTP expires after 24 hours and allows a maximum of 10 attempts. If you run into any difficulties receiving the OTP code, you can also create an account on console.agentmail.to using the human email address you provided to verify your account.

CLI:

bash
agentmail agent verify --otp-code 123456

OpenAPI Specification

yaml
openapi: 3.1.0
info:
  title: api
  version: 1.0.0
paths:
  /v0/agent/verify:
    post:
      operationId: verify
      summary: Verify
      description: >-
        Verify an agent organization using the 6-digit OTP sent to the human's
        email during sign-up.

        On success, the organization is upgraded from `agent_unverified` to
        `agent_verified`, the send allowlist is removed, and free plan
        entitlements are applied.

        The OTP expires after 24 hours and allows a maximum of 10 attempts. If
        you run into any difficulties receiving the OTP code, you can also
        create an account on
        [console.agentmail.to](https://console.agentmail.to) using the human
        email address you provided to verify your account.

        **CLI:**

        ```bash

        agentmail agent verify --otp-code 123456

        ```
      tags:
        - subpackage_agent
      parameters:
        - name: Authorization
          in: header
          description: Bearer authentication
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Response with status 200
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/type_agent:AgentVerifyResponse'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/type_agent:AgentVerifyRequest'
servers:
  - url: https://api.agentmail.to
    description: prod
  - url: https://x402.api.agentmail.to
    description: prod-x402
  - url: https://mpp.api.agentmail.to
    description: prod-mpp
  - url: https://api.agentmail.eu
    description: eu-prod
components:
  schemas:
    type_agent:AgentVerifyRequest:
      type: object
      properties:
        otp_code:
          type: string
          description: 6-digit verification code sent to the human's email address.
      required:
        - otp_code
      description: Request body to verify an agent with an OTP code.
      title: AgentVerifyRequest
    type_agent:AgentVerifyResponse:
      type: object
      properties:
        verified:
          type: boolean
          description: Whether the organization was verified.
      required:
        - verified
      description: Response after successful agent verification.
      title: AgentVerifyResponse
  securitySchemes:
    Bearer:
      type: http
      scheme: bearer

Examples

Request

json
{
  "otp_code": "otp_code"
}

Response

json
{
  "verified": true
}

SDK Code

typescript
import { AgentMailClient } from "agentmail";

async function main() {
    const client = new AgentMailClient({
        apiKey: "YOUR_TOKEN_HERE",
    });
    await client.agent.verify({
        otpCode: "otp_code",
    });
}
main();
python
from agentmail import AgentMail

client = AgentMail(
    api_key="YOUR_TOKEN_HERE",
)

client.agent.verify(
    otp_code="otp_code",
)
go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.agentmail.to/v0/agent/verify"

	payload := strings.NewReader("{\n  \"otp_code\": \"otp_code\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <api_key>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
ruby
require 'uri'
require 'net/http'

url = URI("https://api.agentmail.to/v0/agent/verify")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <api_key>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"otp_code\": \"otp_code\"\n}"

response = http.request(request)
puts response.read_body
java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.agentmail.to/v0/agent/verify")
  .header("Authorization", "Bearer <api_key>")
  .header("Content-Type", "application/json")
  .body("{\n  \"otp_code\": \"otp_code\"\n}")
  .asString();
php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.agentmail.to/v0/agent/verify', [
  'body' => '{
  "otp_code": "otp_code"
}',
  'headers' => [
    'Authorization' => 'Bearer <api_key>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
csharp
using RestSharp;

var client = new RestClient("https://api.agentmail.to/v0/agent/verify");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <api_key>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"otp_code\": \"otp_code\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
swift
import Foundation

let headers = [
  "Authorization": "Bearer <api_key>",
  "Content-Type": "application/json"
]
let parameters = ["otp_code": "otp_code"] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.agentmail.to/v0/agent/verify")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()