Domani Verify Service API

The Verify Service API from Domani — 1 operation(s) for verify service.

Operations 2

POST /api/domains/{domain}/verify-service Add DNS records to verify domain ownership for a third-party service #
GET /api/domains/{domain}/verify-service List supported services for domain verification #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • 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.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/domani-run:domani-run-verify-service-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.

Get an API key

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 Specification

domani-run-verify-service-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: domani.run Verify Service API
  version: 1.0.0
  description: 'Domain infrastructure for AI agents. One API to search, register, and connect domain names.


    ## Authentication


    All authenticated endpoints require a Bearer token:


    ```

    Authorization: Bearer domani_sk_xxx

    ```


    Get your API key by registering:


    ```bash

    curl -X POST https://domani.run/api/auth/register \

    -H "Content-Type: application/json" \

    -d ''{"email": "you@example.com"}''

    ```


    ## Rate Limits


    Every response includes `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset` headers. When rate limited (HTTP 429), check the `Retry-After` header for seconds to wait.


    ## Error Handling


    All errors return a consistent JSON envelope with `error`, `code`, `hint`, and `documentation_url` fields. Use the `code` field for programmatic handling and the `hint` field for recovery guidance.


    ## MCP Server


    A real-time MCP (Model Context Protocol) server is available at `POST /mcp` using Streamable HTTP transport. Connect any MCP-compatible agent (Claude Code, Cursor, etc.) with your Bearer token for typed tool access (search, buy, DNS, etc.).


    ## Pagination


    The `GET /api/tlds` endpoint supports `limit` and `offset` query parameters. When paginated, the response includes a `Link` header with `rel="next"` for the next page.'
  contact:
    name: domani.run
    url: https://domani.run
servers:
- url: https://domani.run
  description: Production
security:
- BearerAuth: []
tags:
- name: Verify Service
paths:
  /api/domains/{domain}/verify-service:
    post:
      operationId: verifyService
      summary: Add DNS records to verify domain ownership for a third-party service
      description: 'Adds the correct DNS records (TXT, CNAME) to prove domain ownership to a third-party service. Supports Stripe, Google Search Console, AWS SES, Postmark, Resend, Facebook, HubSpot, and Microsoft 365. Unknown service names fall back to a generic TXT record.


        Records are merged with existing DNS - existing records are preserved.


        Mail routing: a change to where the domain''s mail is delivered (its MX or NS records, the address records an MX host inside the zone resolves through, or those of a host that receives Domani mail and publishes no MX) needs the `email:auth_secrets` scope, since whoever receives the mail receives its sign-in codes. Without it the request answers 403 INSUFFICIENT_SCOPE before anything changes, and a token confined to mailboxes answers 403 MAILBOX_CONFINED even with it. Other records need only `domains:write`. Every routing change is recorded in the audit log.'
      tags:
      - Verify Service
      x-rateLimit:
        limit: 30
        window: 1 minute
      x-codeSamples:
      - lang: bash
        label: cURL - Stripe verification
        source: "curl -X POST https://domani.run/api/domains/mysite.com/verify-service \\\n  -H \"Authorization: Bearer domani_sk_xxx\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"service\": \"stripe\", \"token\": \"abc123def456\"}'"
      - lang: bash
        label: cURL - Google Search Console
        source: "curl -X POST https://domani.run/api/domains/mysite.com/verify-service \\\n  -H \"Authorization: Bearer domani_sk_xxx\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"service\": \"google-search-console\", \"token\": \"abcdef123456\"}'"
      parameters:
      - name: domain
        in: path
        required: true
        schema:
          type: string
          example: mysite.com
        description: Domain name you own
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - service
              - token
              properties:
                service:
                  type: string
                  description: Service name (e.g. stripe, google-search-console, aws-ses, postmark, resend, facebook, hubspot, microsoft-365)
                  example: stripe
                token:
                  type: string
                  description: Verification token provided by the service
                  example: abc123def456
            examples:
              stripe:
                summary: Stripe
                value:
                  service: stripe
                  token: abc123def456
              google:
                summary: Google Search Console
                value:
                  service: google-search-console
                  token: abcdef123456
              aws:
                summary: AWS SES
                value:
                  service: aws-ses
                  token: EXAMPLE+abc123
              generic:
                summary: Generic (any service)
                value:
                  service: my-saas
                  token: verify-my-domain-xyz
      responses:
        '200':
          description: Verification records added
          headers:
            X-RateLimit-Limit:
              description: Maximum requests allowed in the current window
              schema:
                type: integer
              example: 60
            X-RateLimit-Remaining:
              description: Requests remaining in the current window
              schema:
                type: integer
              example: 57
            X-RateLimit-Reset:
              description: Unix timestamp (seconds) when the window resets
              schema:
                type: integer
              example: 1700000000
          content:
            application/json:
              schema:
                type: object
                properties:
                  domain:
                    type: string
                  service:
                    type: string
                  service_display_name:
                    type: string
                  known_service:
                    type: boolean
                  records_added:
                    type: array
                    items:
                      $ref: '#/components/schemas/DnsRecord'
                  total_records:
                    type: integer
                  docs:
                    type: string
                    format: uri
                    nullable: true
                  hint:
                    type: string
              example:
                domain: mysite.com
                service: stripe
                service_display_name: Stripe
                known_service: true
                records_added:
                - type: TXT
                  name: '@'
                  value: stripe-verification=abc123def456
                  ttl: 3600
                total_records: 3
                docs: https://docs.stripe.com/identity/verification-checks/selfie#domain-verification
                hint: Stripe verification records added. Return to Stripe to complete verification.
        '400':
          description: Invalid request parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Missing 'service' parameter
                code: MISSING_PARAMETER
                hint: 'Send { service: ''stripe'', token: ''your-token'' }'
                documentation_url: https://domani.run/llms.txt
        '401':
          description: Missing or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                missing:
                  summary: No Authorization header
                  value:
                    error: Missing API key
                    code: MISSING_API_KEY
                    hint: 'Include ''Authorization: Bearer domani_sk_xxx'' header'
                    documentation_url: https://domani.run/llms.txt
                invalid:
                  summary: Invalid or revoked key
                  value:
                    error: Invalid API key
                    code: INVALID_API_KEY
                    hint: Check your API key or create a new one at POST /api/tokens
                    documentation_url: https://domani.run/llms.txt
                expired:
                  summary: Token has expired
                  value:
                    error: API key has expired
                    code: EXPIRED_API_KEY
                    hint: Create a new token via POST /api/tokens or run 'domani login'
                    documentation_url: https://domani.run/llms.txt
        '403':
          description: Moving the domain's mail needs the email:auth_secrets scope (INSUFFICIENT_SCOPE) and a token not confined to mailboxes (MAILBOX_CONFINED)
        '404':
          description: Domain not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Domain not found
                code: NOT_FOUND
                hint: Verify the domain exists and belongs to you
                documentation_url: https://domani.run/llms.txt
        '429':
          description: Rate limit exceeded - wait and retry
          headers:
            X-RateLimit-Limit:
              description: Maximum requests allowed in the current window
              schema:
                type: integer
              example: 60
            X-RateLimit-Remaining:
              description: Requests remaining in the current window
              schema:
                type: integer
              example: 57
            X-RateLimit-Reset:
              description: Unix timestamp (seconds) when the window resets
              schema:
                type: integer
              example: 1700000000
            Retry-After:
              description: Seconds to wait before retrying
              schema:
                type: integer
              example: 30
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Rate limit exceeded
                code: RATE_LIMIT_EXCEEDED
                hint: Wait 30 seconds before retrying
                retry_after: 30
                documentation_url: https://domani.run/llms.txt
    get:
      operationId: listVerifyServices
      summary: List supported services for domain verification
      description: Returns all known services with their names, descriptions, and documentation URLs. Unknown services fall back to a generic TXT record.
      tags:
      - Verify Service
      x-rateLimit:
        limit: 60
        window: 1 minute
      parameters:
      - name: domain
        in: path
        required: true
        schema:
          type: string
          example: mysite.com
        description: Domain name you own
      responses:
        '200':
          description: Available services
          headers:
            X-RateLimit-Limit:
              description: Maximum requests allowed in the current window
              schema:
                type: integer
              example: 60
            X-RateLimit-Remaining:
              description: Requests remaining in the current window
              schema:
                type: integer
              example: 57
            X-RateLimit-Reset:
              description: Unix timestamp (seconds) when the window resets
              schema:
                type: integer
              example: 1700000000
          content:
            application/json:
              schema:
                type: object
                properties:
                  domain:
                    type: string
                  services:
                    type: array
                    items:
                      type: object
                      properties:
                        name:
                          type: string
                        displayName:
                          type: string
                        description:
                          type: string
                        docs:
                          type: string
                          format: uri
                  hint:
                    type: string
        '401':
          description: Missing or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                missing:
                  summary: No Authorization header
                  value:
                    error: Missing API key
                    code: MISSING_API_KEY
                    hint: 'Include ''Authorization: Bearer domani_sk_xxx'' header'
                    documentation_url: https://domani.run/llms.txt
                invalid:
                  summary: Invalid or revoked key
                  value:
                    error: Invalid API key
                    code: INVALID_API_KEY
                    hint: Check your API key or create a new one at POST /api/tokens
                    documentation_url: https://domani.run/llms.txt
                expired:
                  summary: Token has expired
                  value:
                    error: API key has expired
                    code: EXPIRED_API_KEY
                    hint: Create a new token via POST /api/tokens or run 'domani login'
                    documentation_url: https://domani.run/llms.txt
        '404':
          description: Domain not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Domain not found
                code: NOT_FOUND
                hint: Verify the domain exists and belongs to you
                documentation_url: https://domani.run/llms.txt
        '429':
          description: Rate limit exceeded - wait and retry
          headers:
            X-RateLimit-Limit:
              description: Maximum requests allowed in the current window
              schema:
                type: integer
              example: 60
            X-RateLimit-Remaining:
              description: Requests remaining in the current window
              schema:
                type: integer
              example: 57
            X-RateLimit-Reset:
              description: Unix timestamp (seconds) when the window resets
              schema:
                type: integer
              example: 1700000000
            Retry-After:
              description: Seconds to wait before retrying
              schema:
                type: integer
              example: 30
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Rate limit exceeded
                code: RATE_LIMIT_EXCEEDED
                hint: Wait 30 seconds before retrying
                retry_after: 30
                documentation_url: https://domani.run/llms.txt
components:
  schemas:
    Error:
      type: object
      properties:
        error:
          type: string
          description: Human-readable error message
        code:
          type: string
          description: Machine-readable error code
          enum:
          - MISSING_API_KEY
          - INVALID_API_KEY
          - EXPIRED_API_KEY
          - MISSING_PARAMETER
          - INVALID_DOMAIN
          - PAYMENT_REQUIRED
          - DOMAIN_UNAVAILABLE
          - RATE_LIMIT_EXCEEDED
          - USER_EXISTS
          - NOT_FOUND
          - UNKNOWN_PROVIDER
          - UNKNOWN_METHOD
          - TARGET_REQUIRED
          - INVALID_PARAMETER
          - CONTACT_REQUIRED
          - INVALID_CONTACT
          - INSUFFICIENT_SCOPE
          - SCOPE_ESCALATION
          - MAILBOX_CONFINED
          - CONFIRMATION_REQUIRED
          - OWN_SENDER
          - INVALID_SENDER_RULE
          - SENDER_RULE_NOT_FOUND
          - SENDER_RULE_LIMIT
          - SENDER_RULES_UNAVAILABLE
          - INVALID_KIND
          - MAIL_KIND_OFF
          - UNSUBSCRIBE_UNAVAILABLE
          - UNSUBSCRIBE_FAILED
          - DOMAIN_EXISTS
          - DOMAIN_NOT_ACTIVE
          - UNSUPPORTED_TLD
          - TLD_NOT_IN_PUBLIC_DNS
          - REGISTRANT_NOT_ELIGIBLE
          - NOT_AVAILABLE
          - ALREADY_REGISTERED
          - TRANSFER_NOT_ELIGIBLE
          - RENEWAL_NOT_ELIGIBLE
          - ALREADY_LISTED
          - LISTING_SOLD
          - SELF_PURCHASE
          - DESCRIPTION_TOO_LONG
          - DEAL_NOT_FOUND
          - INVALID_DEAL_STATE
          - EPP_ATTEMPTS_EXCEEDED
          - ACTIVE_DEAL_EXISTS
          - AGENT_IDENTITY_NOT_FOUND
          - AGENT_IDENTITY_ESCALATION
          - AGENT_MAILBOXES_REQUIRED
          - CREDENTIAL_REVOKE_FAILED
          - INVALID_IDEMPOTENCY_KEY
          - IDEMPOTENCY_KEY_MISMATCH
          - IDEMPOTENCY_KEY_REUSED
          - OPERATION_IN_PROGRESS
          - OPERATION_SUPERSEDED
          - INVALID_OPERATION_RECEIPT
          - WORKSPACE_ADMIN_REQUIRED
          - WORKSPACE_OWNER_REQUIRED
          - PRINCIPAL_NOT_IN_WORKSPACE
          - MAILBOX_NOT_IN_WORKSPACE
          - GROUP_NOT_IN_WORKSPACE
          - COLLECTION_NOT_IN_WORKSPACE
          - ACCESS_VERSION_CONFLICT
          - ACCESS_OFFER_INVALID
          - ACCESS_OFFER_EMAIL_MISMATCH
          - MAIL_DOMAIN_CAPACITY_EXHAUSTED
          - MAIL_PROVIDER_ERROR
          - INVALID_HTTP_ROUTE_HOSTNAME
          - INVALID_HTTP_ROUTE_UPSTREAM
          - INVALID_HTTP_ROUTE_UPSTREAM_HEADERS
          - INVALID_HTTP_ROUTE_LEASE
          - INVALID_HTTP_ROUTE_POLICY
          - INVALID_HOSTNAME_BINDING
          - HTTP_ROUTE_HOSTNAME_NOT_ALLOWED
          - HTTP_ROUTE_HOSTNAME_REQUIRED
          - HTTP_ROUTE_HOSTNAME_RESERVED
          - HTTP_ROUTE_HOSTNAME_UNAVAILABLE
          - HTTP_ROUTE_CONCURRENCY_LIMIT
          - HTTP_ROUTE_WORKSPACE_LIMIT
          - HTTP_ROUTE_DOMAIN_NOT_OWNED
          - HTTP_ROUTE_TERMINAL
          - HTTP_ROUTE_VERIFICATION_NOT_ENABLED
          - HTTP_ROUTE_VERIFICATION_REQUIRES_HTTPS
          - HTTP_ROUTE_POLICY_WITHOUT_SCOPE
          - HTTP_ROUTE_POLICY_REQUIRED
          - HTTP_ROUTE_AGENT_IDENTITY_REQUIRED
          - HTTP_ROUTE_POLICY_ESCALATION
          - HOSTNAME_BINDING_NOT_ACTIVE
          - HOSTNAME_BINDING_DNS_CONFLICT
          - HOSTNAME_BINDING_ACK_REQUIRED
          - HOSTNAME_BINDING_BROWSER_MODE_MISMATCH
          - HOSTNAME_DNS_CONFLICT
          - ZONE_READ_FAILED
          - DNS_VERSION_CONFLICT
          - UNAUTHORIZED
          - APEX_WEB_MODE_CONFLICT
          - APEX_DELEGATION_ACK_REQUIRED
          - VERIFICATION_COOLDOWN
          - VERIFICATION_SEND_FAILED
          - UPGRADE_REQUIRED
          - FREE_LIMIT_EXCEEDED
        upgrade_plan:
          type: object
          nullable: true
          description: 'On UPGRADE_REQUIRED / FREE_LIMIT_EXCEEDED: the cheapest plan that would give room for another mailbox, named from the catalog of the host the request came in on (Mailzero''s own plan on the mail host, Domani''s elsewhere). null when no plan in that catalog has more room.'
          properties:
            key:
              type: string
            name:
              type: string
            priceUsd:
              type: number
            mailboxes:
              type: integer
              nullable: true
        plan_limit:
          type: integer
          nullable: true
          description: 'On UPGRADE_REQUIRED / FREE_LIMIT_EXCEEDED: the current plan''s own mailbox limit (0 when the plan includes none, null when unlimited), so callers can tell a plan without mailboxes from a plan whose mailboxes are all in use.'
        hint:
          type: string
          description: Actionable recovery guidance for the caller
        fix_command:
          type: string
          description: CLI command to resolve the error (e.g. 'domani login', 'domani billing'). Present in CLI --json output.
        documentation_url:
          type: string
          format: uri
          description: Link to relevant documentation
        setup_url:
          type: string
          format: uri
          description: URL to resolve the issue (e.g. add payment method)
        fix_url:
          type: string
          format: uri
          description: URL to resolve the issue (alias for setup_url in CLI --json output)
        retry_after:
          type: integer
          description: Seconds until retry is allowed (present on 429 responses)
        retry_after_minutes:
          type: integer
          description: Minutes until another verification email may be requested
        retryable:
          type: boolean
          description: Whether retrying after the external condition changes is safe
      required:
      - error
      - code
      - documentation_url
      example:
        error: Missing API key
        code: MISSING_API_KEY
        hint: 'Include ''Authorization: Bearer domani_sk_xxx'' header'
        documentation_url: https://domani.run/llms.txt
    DnsRecord:
      type: object
      properties:
        type:
          type: string
          enum:
          - A
          - AAAA
          - CNAME
          - MX
          - TXT
          - NS
          - SRV
          - CAA
          - TLSA
          description: DNS record type. TLSA publishes a DANE record; its value is the rdata 'usage selector matching-type hex-data'.
        name:
          type: string
          example: '@'
          description: Record name (@ for root, or subdomain, e.g. _443._tcp for TLSA)
        value:
          type: string
          example: 76.76.21.21
          description: Record value (IP address, hostname, or TLSA rdata like '3 1 1 abc123...')
        ttl:
          type: integer
          example: 3600
          description: Time to live in seconds
        priority:
          type: integer
          description: Priority value (required for MX records)
        required:
          type: boolean
          description: False when the zone Domani manages for the domain cannot hold the record (a TXT longer than the registrar accepts); such a record is shown but not needed for mail to work. Absent on plain zone records.
      required:
      - type
      - name
      - value
      - ttl
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: domani_sk_xxx
      description: 'API key obtained by signing in (POST /api/auth/register starts email verification; a CLI or agent gets the key itself via the device-login flow, POST /api/auth/cli then GET /api/auth/cli/poll). Include as: `Authorization: Bearer domani_sk_xxx`. Keys use the prefix `domani_sk_` followed by 32 random characters.'
externalDocs:
  description: Interactive API Reference
  url: https://domani.run/docs