> ## Documentation Index
> Fetch the complete documentation index at: https://docs.firma.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Verify DNS records

> Verify that all required DNS records (SPF, DKIM, DMARC) are properly configured. Call this after adding all DNS records from the finalize step. Once verified, the domain is ready for sending emails.



## OpenAPI

````yaml api-reference/v01.30.00/openapi-v01.30.00.json post /company/domains/{id}/verify-dns
openapi: 3.0.3
info:
  title: Firma Partner API
  description: >-
    RESTful API for document signing and template management.


    **Authentication**: All endpoints require API key authentication via the
    `Authorization` header. Use your API key directly without any prefix (e.g.,
    `your-api-key`). The Bearer prefix is optional but not required.


    **Security Features**:

    - Input validation using Zod schemas with detailed field-level error
    messages

    - RSA-256 signed JWT tokens for embedded template access


    **Rate Limiting**: Rate limits are tiered based on operation type:

    - Read operations (GET): 200 requests per minute

    - Write operations (POST/PUT/PATCH/DELETE): 120 requests per minute

    - Webhook CRUD operations: 60 requests per minute

    - Webhook test: 10 requests per minute

    - API key regeneration/expiration: 1 request per minute

    - Webhook secret rotation: 1 request per minute


    When rate limits are exceeded, the API returns a `429 Too Many Requests`
    response with headers:

    - `X-RateLimit-Limit`: Maximum requests per minute for this endpoint

    - `X-RateLimit-Remaining`: Requests remaining in current window

    - `X-RateLimit-Reset`: Unix timestamp when limit resets

    - `Retry-After`: Seconds until retry is allowed


    **Error Handling**: All errors return structured JSON responses with `error`
    (human-readable message), `code` (machine-readable identifier), and
    `details` (field-level validation errors when applicable).


    **Embedded Template Integration**: The Firma Template Editor can be embedded
    in your application using a standalone JavaScript library.


    ```html

    <!-- Load the Firma Template Editor library -->

    <script
    src="https://api.firma.dev/functions/v1/embed-proxy/template-editor.js"></script>


    <script>

    // Generate JWT token via API first

    fetch('https://api.firma.dev/functions/v1/signing-request-api/generate-template-token',
    {
      method: 'POST',
      headers: {
        'Authorization': 'YOUR_API_KEY',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        companies_workspaces_templates_id: 'template-id'
      })
    })

    .then(res => res.json())

    .then(data => {
      // Initialize editor with JWT token
      window.FirmaTemplateEditor.init({
        container: '#firma-editor-container',
        jwt: data.token,
        templateId: 'template-id',
        theme: 'dark',
        readOnly: false,
        onSave: (savedData) => {
          console.log('Template saved:', savedData);
        },
        onError: (error) => {
          console.error('Editor error:', error);
        },
        onLoad: (template) => {
          console.log('Template loaded:', template);
        }
      });
    });

    ```
  version: 01.30.00
  contact:
    name: API Support
    url: https://firma.com/support
servers:
  - url: https://api.firma.dev/functions/v1/signing-request-api
    description: Production API - Recommended (Current)
  - url: https://api.firma.dev/api/v1
    description: Production API - Planned
security:
  - ApiKeyAuth: []
tags:
  - name: Company
    description: Company information and settings
  - name: Workspaces
    description: Workspace management operations
  - name: Templates
    description: Template management operations
  - name: Signing Requests
    description: Document signing request operations
  - name: Custom Fields
    description: >-
      Custom field definition management for workspaces, templates, and signing
      requests
  - name: Webhooks
    description: Webhook configuration and management
  - name: JWT Management
    description: JWT token generation and revocation for embedded templates
  - name: Workspace Settings
    description: Workspace configuration and settings
  - name: Email Domains
    description: >-
      Email domain setup and verification for sending signing request emails
      from custom domains
  - name: Email Templates
    description: >-
      Email template management for workspace and company-level customization of
      signing request notifications
  - name: Signer Terms
    description: >-
      Custom signer terms-of-service / consent statements, company-level with
      per-language workspace overrides
paths:
  /company/domains/{id}/verify-dns:
    post:
      tags:
        - Email Domains
      summary: Verify DNS records
      description: >-
        Verify that all required DNS records (SPF, DKIM, DMARC) are properly
        configured. Call this after adding all DNS records from the finalize
        step. Once verified, the domain is ready for sending emails.
      operationId: verifyCompanyDomainDns
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
          description: Domain ID
      responses:
        '200':
          description: DNS verification result
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DomainVerifyDnsResponse'
              examples:
                verified:
                  summary: All records verified
                  value:
                    verified: true
                    message: Domain is fully verified and ready to send emails
                    domain:
                      id: 123e4567-e89b-12d3-a456-426614174000
                      domain: acme.com
                      verification_status: 2
                      domain_status: 1
                      is_primary: true
                    dns_records:
                      - type: TXT
                        name: '@'
                        value: v=spf1 include:amazonses.com ~all
                        status: verified
                      - type: CNAME
                        name: resend._domainkey
                        value: resend._domainkey.amazonses.com
                        status: verified
                      - type: TXT
                        name: _dmarc
                        value: v=DMARC1; p=none;
                        status: verified
                pending:
                  summary: Some records pending
                  value:
                    verified: false
                    message: >-
                      Some DNS records are not yet verified. Please check your
                      DNS configuration.
                    domain:
                      id: 123e4567-e89b-12d3-a456-426614174000
                      domain: acme.com
                      verification_status: 2
                      domain_status: 0
                    dns_records:
                      - type: TXT
                        name: '@'
                        value: v=spf1 include:amazonses.com ~all
                        status: verified
                      - type: CNAME
                        name: resend._domainkey
                        value: resend._domainkey.amazonses.com
                        status: pending
                      - type: TXT
                        name: _dmarc
                        value: v=DMARC1; p=none;
                        status: pending
        '400':
          description: Domain not finalized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Domain not finalized
                message: >-
                  Please finalize domain setup first by calling POST
                  /company/domains/{id}/finalize
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFoundError'
        '429':
          $ref: '#/components/responses/RateLimitError'
      security:
        - ApiKeyAuth: []
      x-codeSamples:
        - lang: TypeScript
          label: '@firma-dev/sdk'
          source: |-
            import { FirmaClient } from "@firma-dev/sdk";

            const firma = new FirmaClient({ apiKey: "YOUR_API_KEY" });

            const response = await firma.emailDomains.verifyCompanyDomainDns({
                id: "id"
            });
            console.log(response);
components:
  schemas:
    DomainVerifyDnsResponse:
      type: object
      properties:
        verified:
          type: boolean
          description: Whether all DNS records are verified
        message:
          type: string
        domain:
          $ref: '#/components/schemas/Domain'
        dns_records:
          type: array
          items:
            $ref: '#/components/schemas/DomainDnsRecord'
          description: Status of each DNS record
      description: DNS verification result
      required:
        - verified
        - message
        - domain
    Error:
      type: object
      properties:
        error:
          type: string
          description: Human-readable error message
        message:
          type: string
          description: Detailed error description
        details:
          type: object
          description: Additional error details
          additionalProperties: true
      required:
        - error
    Domain:
      type: object
      description: Email domain configuration for sending signing request emails
      properties:
        id:
          type: string
          format: uuid
          description: Unique identifier for the domain
        domain:
          type: string
          description: The domain name (e.g., 'example.com')
        verification_status:
          type: integer
          enum:
            - 0
            - 1
            - 2
          description: >-
            Domain ownership verification status: 0=pending, 1=ownership
            verified (TXT record confirmed), 2=finalized (registered with email
            provider)
        domain_status:
          type: integer
          enum:
            - 0
            - 1
          description: >-
            Email sending status: 0=DNS records pending verification, 1=fully
            verified and ready to send
        is_primary:
          type: boolean
          description: >-
            Whether this is the primary domain for sending emails from this
            workspace
        verification_token:
          type: string
          description: >-
            Token to add as TXT record for domain ownership verification. Only
            returned when verification_status=0.
        resend_domain_id:
          type: string
          nullable: true
          description: External email provider domain ID (internal use)
        dns_records:
          type: array
          nullable: true
          description: >-
            Required DNS records for email sending. Only returned after domain
            finalization (verification_status=2).
          items:
            $ref: '#/components/schemas/DomainDnsRecord'
        date_created:
          type: string
          format: date-time
          description: Domain creation timestamp
        date_changed:
          type: string
          format: date-time
          description: Domain last update timestamp
      required:
        - id
        - domain
        - domain_status
        - verification_status
    DomainDnsRecord:
      type: object
      description: DNS record required for email domain verification
      properties:
        type:
          type: string
          enum:
            - TXT
            - CNAME
            - MX
          description: DNS record type
        name:
          type: string
          description: DNS record name/host (e.g., 'resend._domainkey' or '@')
        value:
          type: string
          description: DNS record value
        ttl:
          type: string
          description: Time to live (e.g., 'Auto' or seconds)
        priority:
          type: integer
          nullable: true
          description: Priority for MX records
        status:
          type: string
          enum:
            - pending
            - verified
            - failed
          description: Verification status of this specific record
  responses:
    UnauthorizedError:
      description: Unauthorized - Invalid or missing API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Unauthorized
            message: Invalid API key
    NotFoundError:
      description: Not Found - Resource does not exist
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Not Found
            message: The requested resource was not found
    RateLimitError:
      description: Too Many Requests - Rate limit exceeded
      headers:
        X-RateLimit-Limit:
          schema:
            type: integer
          description: Maximum requests per minute
        X-RateLimit-Remaining:
          schema:
            type: integer
          description: Requests remaining
        X-RateLimit-Reset:
          schema:
            type: integer
          description: Unix timestamp of reset
        Retry-After:
          schema:
            type: integer
          description: Seconds until retry allowed
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Rate Limit Exceeded
            message: Too many requests. Please wait before retrying.
            details:
              retry_after: 45
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: Authorization
      description: >-
        API key for authentication. Use your API key directly without any prefix
        (e.g., 'your-api-key'). Bearer prefix is optional but not required.

````