> ## 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 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.03.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: Legacy
    description: Deprecated endpoints maintained for backward compatibility
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.
      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:
                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
              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: []
components:
  schemas:
    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
    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
    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
  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.

````