openapi: 3.1.0
info:
  title: Bindizr HTTP API
  description: This is the API documentation for Bindizr
  contact:
    email: kevin136583@gmail.com
  license:
    name: Apache 2.0
    url: http://www.apache.org/licenses/LICENSE-2.0.html
  version: 0.1.0-beta.6
paths:
  /health:
    get:
      tags:
      - Health
      summary: Health probe
      description: Runs a minimal database query and reports whether the API can serve requests. Unauthenticated, intended for load-balancer and orchestrator probes; deeper checks (DNS listener, secondary sync) belong to 'bindizr doctor'.
      operationId: get_health
      responses:
        '200':
          description: Service healthy
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HealthResponse'
        '503':
          description: Service unhealthy
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HealthResponse'
  /notify/zones:
    post:
      tags:
      - Notify
      summary: Send DNS NOTIFY messages for a zone or all zones
      operationId: notify_zones
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/NotifyZoneRequest'
        required: true
      responses:
        '200':
          description: DNS NOTIFY sent successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageResponse'
        '400':
          description: Bad request, invalid input
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Zone not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '415':
          description: Unsupported media type, expected JSON request body
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /records:
    get:
      tags:
      - Record
      summary: List all DNS records
      operationId: get_records
      parameters:
      - name: zone_name
        in: query
        description: The name of the DNS zone to filter records by.
        required: false
        schema:
          type: string
      - name: name
        in: query
        description: Filter by record name.
        required: false
        schema:
          type: string
      - name: record_type
        in: query
        description: Filter by record type.
        required: false
        schema:
          type: string
      - name: value
        in: query
        description: Partially filter by record value.
        required: false
        schema:
          type: string
      - name: ttl
        in: query
        description: Filter by TTL.
        required: false
        schema:
          type: integer
          format: int32
      - name: min_ttl
        in: query
        description: Filter by minimum TTL.
        required: false
        schema:
          type: integer
          format: int32
      - name: max_ttl
        in: query
        description: Filter by maximum TTL.
        required: false
        schema:
          type: integer
          format: int32
      - name: priority
        in: query
        description: Filter by priority.
        required: false
        schema:
          type: integer
          format: int32
      - name: min_priority
        in: query
        description: Filter by minimum priority.
        required: false
        schema:
          type: integer
          format: int32
      - name: max_priority
        in: query
        description: Filter by maximum priority.
        required: false
        schema:
          type: integer
          format: int32
      - name: search
        in: query
        description: Partially search records.
        required: false
        schema:
          type: string
      - name: limit
        in: query
        description: Maximum number of records to return.
        required: false
        schema:
          type: integer
          format: int32
          minimum: 0
      - name: offset
        in: query
        description: Number of records to skip.
        required: false
        schema:
          type: integer
          format: int64
          minimum: 0
      responses:
        '200':
          description: A list of DNS records
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RecordListResponse'
        '400':
          description: Bad request, invalid pagination
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    post:
      tags:
      - Record
      summary: Create a new DNS record
      operationId: create_record
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateRecordRequest'
        required: true
      responses:
        '201':
          description: DNS record created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RecordResponse'
        '400':
          description: Bad request, invalid input
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '415':
          description: Unsupported media type, expected JSON request body
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /records/{record_id}:
    get:
      tags:
      - Record
      summary: Get a specific DNS record
      operationId: get_record
      parameters:
      - name: record_id
        in: path
        description: The ID of the DNS record to retrieve.
        required: true
        schema:
          type: integer
          format: int32
      responses:
        '200':
          description: Details of the DNS record
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RecordResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Record not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    put:
      tags:
      - Record
      summary: Update a specific DNS record
      operationId: update_record
      parameters:
      - name: record_id
        in: path
        description: The ID of the DNS record to update.
        required: true
        schema:
          type: integer
          format: int32
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateRecordRequest'
        required: true
      responses:
        '200':
          description: DNS record updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RecordResponse'
        '400':
          description: Bad request, invalid input
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Record not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '415':
          description: Unsupported media type, expected JSON request body
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    delete:
      tags:
      - Record
      summary: Delete a specific DNS record
      operationId: delete_record
      parameters:
      - name: record_id
        in: path
        description: The ID of the DNS record to delete.
        required: true
        schema:
          type: integer
          format: int32
      responses:
        '200':
          description: DNS record deleted successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Record not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /tsig-keys:
    get:
      tags:
      - TSIG
      summary: List all TSIG keys
      description: Lists every TSIG key without its secret. Fetch a single key to read the secret.
      operationId: get_tsig_keys
      responses:
        '200':
          description: All TSIG keys
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TsigKeyListResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    post:
      tags:
      - TSIG
      summary: Create a TSIG key
      description: Creates a TSIG key. When `secret` is omitted a random secret is generated; when provided it must be valid base64 (imports an existing key). Setting `global` makes the key able to update every zone (all names, all types) without any policy — effectively write access to all DNS data, so use it sparingly. The response includes the secret.
      operationId: create_tsig_key
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateTsigKeyRequest'
        required: true
      responses:
        '201':
          description: TSIG key created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TsigKeyResponse'
        '400':
          description: Bad request, invalid input
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: A TSIG key with the same name already exists
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '415':
          description: Unsupported media type, expected JSON request body
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /tsig-keys/{name}:
    get:
      tags:
      - TSIG
      summary: Get a specific TSIG key
      description: Returns one TSIG key including its secret.
      operationId: get_tsig_key
      parameters:
      - name: name
        in: path
        description: The name of the TSIG key.
        required: true
        schema:
          type: string
      responses:
        '200':
          description: The TSIG key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TsigKeyResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: TSIG key not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    delete:
      tags:
      - TSIG
      summary: Delete a TSIG key
      description: Deletes a TSIG key. Refused while any zone TSIG policy still references it.
      operationId: delete_tsig_key
      parameters:
      - name: name
        in: path
        description: The name of the TSIG key.
        required: true
        schema:
          type: string
      responses:
        '200':
          description: TSIG key deleted successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: TSIG key not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: TSIG key is still referenced by zone TSIG policies
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /zones:
    get:
      tags:
      - Zone
      summary: List all DNS zones
      operationId: get_zones
      parameters:
      - name: name
        in: query
        description: Filter by zone name.
        required: false
        schema:
          type: string
      - name: id
        in: query
        description: Filter by zone ID.
        required: false
        schema:
          type: integer
          format: int32
      - name: primary_ns
        in: query
        description: Filter by primary name server.
        required: false
        schema:
          type: string
      - name: admin_email
        in: query
        description: Filter by admin email.
        required: false
        schema:
          type: string
      - name: ttl
        in: query
        description: Filter by TTL.
        required: false
        schema:
          type: integer
          format: int32
      - name: min_ttl
        in: query
        description: Filter by minimum TTL.
        required: false
        schema:
          type: integer
          format: int32
      - name: max_ttl
        in: query
        description: Filter by maximum TTL.
        required: false
        schema:
          type: integer
          format: int32
      - name: serial
        in: query
        description: Filter by serial.
        required: false
        schema:
          type: integer
          format: int32
      - name: search
        in: query
        description: Partially search zones.
        required: false
        schema:
          type: string
      - name: limit
        in: query
        description: Maximum number of zones to return.
        required: false
        schema:
          type: integer
          format: int32
          minimum: 0
      - name: offset
        in: query
        description: Number of zones to skip.
        required: false
        schema:
          type: integer
          format: int64
          minimum: 0
      responses:
        '200':
          description: A list of DNS zones
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ZoneListResponse'
        '400':
          description: Bad request, invalid pagination
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    post:
      tags:
      - Zone
      summary: Create a new DNS zone
      operationId: create_zone
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateZoneRequest'
        required: true
      responses:
        '201':
          description: DNS zone created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ZoneResponse'
        '400':
          description: Bad request, invalid input
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '415':
          description: Unsupported media type, expected JSON request body
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /zones/{name}:
    get:
      tags:
      - Zone
      summary: Get a specific DNS zone
      operationId: get_zone
      parameters:
      - name: name
        in: path
        description: The name of the DNS zone to retrieve.
        required: true
        schema:
          type: string
      - name: records
        in: query
        description: Whether to include records for the DNS zone.
        required: false
        schema:
          type: boolean
      responses:
        '200':
          description: Details of the DNS zone
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ZoneDetailResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Zone not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    put:
      tags:
      - Zone
      summary: Update a specific DNS zone
      operationId: update_zone
      parameters:
      - name: name
        in: path
        description: The name of the DNS zone to update.
        required: true
        schema:
          type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateZoneRequest'
        required: true
      responses:
        '200':
          description: DNS zone updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ZoneResponse'
        '400':
          description: Bad request, invalid input
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Zone not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '415':
          description: Unsupported media type, expected JSON request body
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    delete:
      tags:
      - Zone
      summary: Delete a specific DNS zone
      operationId: delete_zone
      parameters:
      - name: name
        in: path
        description: The name of the DNS zone to delete.
        required: true
        schema:
          type: string
      responses:
        '200':
          description: DNS zone deleted successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Zone not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /zones/{name}/export:
    get:
      tags:
      - Zone
      summary: Export a zone as BIND master-file text
      description: Renders the zone and its records as an RFC 1035 master file, the inverse of the import endpoint.
      operationId: export_zone
      parameters:
      - name: name
        in: path
        description: The name of the DNS zone to export.
        required: true
        schema:
          type: string
      responses:
        '200':
          description: The zone as master-file text
          content:
            text/plain:
              schema:
                type: string
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Zone not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /zones/{name}/imports:
    post:
      tags:
      - Zone
      summary: Import a BIND zone file into a zone
      description: Parse BIND zone file text and reconcile it with the zone using append/upsert/replace. When applied, the zone serial is incremented once and a single NOTIFY is sent. If any record fails validation nothing is applied and the errors are returned.
      operationId: import_zone
      parameters:
      - name: name
        in: path
        description: The name of the DNS zone to import records into.
        required: true
        schema:
          type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ImportZoneFileRequest'
        required: true
      responses:
        '200':
          description: Import summary and validation errors
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ImportZoneFileResponse'
        '400':
          description: Bad request, invalid input
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Zone not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '415':
          description: Unsupported media type, expected JSON request body
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /zones/{name}/rollback:
    post:
      tags:
      - Zone
      summary: Roll a zone back to a snapshot serial
      description: Restores the zone's record set and SOA metadata to the state captured at the target serial. The zone serial still advances to a new value (serials never go backward) and a single NOTIFY is sent. The zone name is not part of a snapshot and is never changed. With dry_run the rollback is computed and reported without applying any change.
      operationId: rollback_zone
      parameters:
      - name: name
        in: path
        description: The name of the DNS zone to roll back.
        required: true
        schema:
          type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RollbackZoneRequest'
        required: true
      responses:
        '200':
          description: Rollback result
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RollbackZoneResponse'
        '400':
          description: Bad request, invalid target serial
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Zone or snapshot not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '415':
          description: Unsupported media type, expected JSON request body
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /zones/{name}/snapshots:
    get:
      tags:
      - Zone
      summary: List a zone's snapshots (serial history)
      description: Every zone mutation records a snapshot of the zone's SOA metadata keyed by serial. Snapshots are returned newest serial first.
      operationId: list_zone_snapshots
      parameters:
      - name: name
        in: path
        description: The name of the DNS zone.
        required: true
        schema:
          type: string
      - name: limit
        in: query
        description: Maximum number of snapshots to return.
        required: false
        schema:
          type: integer
          format: int32
          minimum: 0
      - name: offset
        in: query
        description: Number of snapshots to skip.
        required: false
        schema:
          type: integer
          format: int64
          minimum: 0
      responses:
        '200':
          description: A list of zone snapshots
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SnapshotListResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Zone not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /zones/{name}/snapshots/diff:
    get:
      tags:
      - Zone
      summary: Diff the records between two of a zone's serials
      description: Reports the RRsets added, removed, and changed between `from` and `to`. Omitting `to` compares against the current serial. Each serial must be the current one or an existing snapshot.
      operationId: diff_zone_snapshots
      parameters:
      - name: name
        in: path
        description: The name of the DNS zone.
        required: true
        schema:
          type: string
      - name: from
        in: query
        description: The serial to diff from.
        required: true
        schema:
          type: integer
          format: int32
      - name: to
        in: query
        description: The serial to diff to; defaults to the current serial.
        required: false
        schema:
          type: integer
          format: int32
      responses:
        '200':
          description: The record differences between the two serials
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SnapshotDiffResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Zone or snapshot not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /zones/{name}/snapshots/{serial}:
    get:
      tags:
      - Zone
      summary: Get the zone state captured at a snapshot serial
      description: Returns the SOA snapshot at the given serial together with the zone's record set at that serial, reconstructed from the change history.
      operationId: get_zone_snapshot
      parameters:
      - name: name
        in: path
        description: The name of the DNS zone.
        required: true
        schema:
          type: string
      - name: serial
        in: path
        description: The snapshot serial to inspect.
        required: true
        schema:
          type: integer
          format: int32
      responses:
        '200':
          description: The snapshot and its reconstructed records
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SnapshotDetailResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Zone or snapshot not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /zones/{name}/status:
    get:
      tags:
      - Zone
      summary: Check how far each secondary has caught up with a zone
      description: Queries every configured secondary for the SOA serial it currently serves and compares it with the zone's serial. Probes run live and in parallel; an unreachable secondary is reported with the failure reason. With no secondaries configured the list is empty.
      operationId: get_zone_status
      parameters:
      - name: name
        in: path
        description: The name of the DNS zone.
        required: true
        schema:
          type: string
      responses:
        '200':
          description: The zone's secondary sync status
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ZoneStatusResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Zone not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /zones/{name}/tsig-policies:
    get:
      tags:
      - TSIG
      summary: List a zone's TSIG policies
      description: 'Lists every TSIG policy of a zone: which keys may update which record names and types via nsupdate.'
      operationId: get_zone_tsig_policies
      parameters:
      - name: name
        in: path
        description: The name of the DNS zone.
        required: true
        schema:
          type: string
      responses:
        '200':
          description: The zone's TSIG policies
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ZoneTsigPolicyListResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Zone not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    post:
      tags:
      - TSIG
      summary: Grant a TSIG key nsupdate rights in a zone
      description: 'Creates a TSIG policy granting the named key nsupdate rights in the zone, optionally restricted by record name pattern (`*`, `@`, `*.sub`, or an exact relative name) and record types (`*` or a comma-separated list). Global keys are rejected: they already cover every zone and never carry policies.'
      operationId: create_zone_tsig_policy
      parameters:
      - name: name
        in: path
        description: The name of the DNS zone.
        required: true
        schema:
          type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateZoneTsigPolicyRequest'
        required: true
      responses:
        '201':
          description: TSIG policy created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ZoneTsigPolicyResponse'
        '400':
          description: Bad request, invalid input
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Zone or TSIG key not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '415':
          description: Unsupported media type, expected JSON request body
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /zones/{name}/tsig-policies/{id}:
    delete:
      tags:
      - TSIG
      summary: Remove a TSIG policy from a zone
      operationId: delete_zone_tsig_policy
      parameters:
      - name: name
        in: path
        description: The name of the DNS zone.
        required: true
        schema:
          type: string
      - name: id
        in: path
        description: The id of the TSIG policy.
        required: true
        schema:
          type: integer
          format: int32
      responses:
        '200':
          description: TSIG policy deleted successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Zone or TSIG policy not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /zones/{zone_name}/records/bulk:
    post:
      tags:
      - Record
      summary: Bulk insert DNS records into a zone
      description: Insert many records into a single zone in one transaction. The zone serial is incremented once and a single NOTIFY is sent. Either all records are inserted or none are. With dry_run the same validation runs but nothing is applied.
      operationId: create_records_bulk
      parameters:
      - name: zone_name
        in: path
        description: The name of the DNS zone to insert records into.
        required: true
        schema:
          type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateBulkRecordsRequest'
        required: true
      responses:
        '200':
          description: Dry run validated successfully, nothing applied
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BulkRecordsResponse'
        '201':
          description: DNS records created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BulkRecordsResponse'
        '400':
          description: Bad request, invalid input
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Zone not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '415':
          description: Unsupported media type, expected JSON request body
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  schemas:
    BulkRecordItem:
      type: object
      description: |-
        A single record entry for bulk insertion. The zone is taken from the request
        path, so unlike [`CreateRecordRequest`] it carries no `zone_name`.
      required:
      - name
      - record_type
      - value
      properties:
        name:
          type: string
          example: sub
        priority:
          type:
          - integer
          - 'null'
          format: int32
          description: MX and SRV priority, set here rather than inline in the value; other record types reject it.
          example: 10
        record_type:
          type: string
          example: A
        ttl:
          type:
          - integer
          - 'null'
          format: int32
          description: Optional; an omitted TTL is fixed to the zone's TTL at write time. Every record of an RRset (same name and type) must share one TTL.
          example: 3600
        value:
          $ref: '#/components/schemas/RecordValueRequest'
    BulkRecordsResponse:
      type: object
      description: |-
        Response for a bulk insert: the count inserted and the created records. On a
        dry run `records` holds the validated would-be records (with placeholder
        IDs) and nothing is inserted.
      required:
      - applied
      - dry_run
      - inserted
      - records
      - diff
      properties:
        applied:
          type: boolean
          example: true
        diff:
          $ref: '#/components/schemas/RecordDiff'
          description: The insert as a record diff (all additions), for previewing the change.
        dry_run:
          type: boolean
          example: false
        inserted:
          type: integer
          example: 3
          minimum: 0
        records:
          type: array
          items:
            $ref: '#/components/schemas/GetRecordResponse'
    CreateBulkRecordsRequest:
      type: object
      description: Request body for bulk-inserting records into a zone.
      required:
      - records
      properties:
        dry_run:
          type: boolean
          description: When true, parse and validate without applying any change.
        records:
          type: array
          items:
            $ref: '#/components/schemas/BulkRecordItem'
    CreateRecordRequest:
      type: object
      description: Request body for creating a record in a named zone.
      required:
      - name
      - record_type
      - value
      - zone_name
      properties:
        name:
          type: string
          example: sub
        priority:
          type:
          - integer
          - 'null'
          format: int32
          description: MX and SRV priority, set here rather than inline in the value; other record types reject it.
          example: 10
        record_type:
          type: string
          example: A
        ttl:
          type:
          - integer
          - 'null'
          format: int32
          description: Optional; an omitted TTL is fixed to the zone's TTL at write time. Every record of an RRset (same name and type) must share one TTL.
          example: 3600
        value:
          $ref: '#/components/schemas/RecordValueRequest'
        zone_name:
          type: string
          example: example.com
    CreateTsigKeyRequest:
      type: object
      description: Request body for creating a TSIG key. Omitting `secret` generates one.
      required:
      - name
      properties:
        algorithm:
          type:
          - string
          - 'null'
          description: Defaults to `hmac-sha256`; also accepts `hmac-sha384` and `hmac-sha512`.
          example: hmac-sha256
        global:
          type: boolean
          description: |-
            Make the key global: it may update every zone (all names, all types)
            without any policy. Fixed at creation.
          example: false
        name:
          type: string
          example: update-key
        secret:
          type:
          - string
          - 'null'
          description: Existing base64 secret to import; omit to generate a random one.
          example: bXktMzItYnl0ZS1pbXBvcnQtc2VjcmV0LWV4YW1wbGU=
    CreateZoneRequest:
      type: object
      description: Request body for creating or updating a zone.
      required:
      - name
      - primary_ns
      - admin_email
      - ttl
      properties:
        admin_email:
          type: string
          example: admin@example.com
        expire:
          type:
          - integer
          - 'null'
          format: int32
          example: 604800
        minimum_ttl:
          type:
          - integer
          - 'null'
          format: int32
          example: 3600
        name:
          type: string
          example: example.com
        primary_ns:
          type: string
          example: ns1.example.com
        refresh:
          type:
          - integer
          - 'null'
          format: int32
          example: 7200
        retry:
          type:
          - integer
          - 'null'
          format: int32
          example: 3600
        serial:
          type:
          - integer
          - 'null'
          format: int32
          description: Starting serial, auto-generated if not provided. Must be 1-2137483647 so the counter keeps room to advance, and can only be set at creation.
          example: 42
        ttl:
          type: integer
          format: int32
          example: 3600
    CreateZoneTsigPolicyRequest:
      type: object
      description: Request body for granting a TSIG key nsupdate rights in a zone.
      required:
      - tsig_key
      properties:
        record_name_pattern:
          type:
          - string
          - 'null'
          description: |-
            `*` (any name), `@` (apex), `*.sub` (subtree) or an exact relative name.
            Defaults to `*`.
          example: '*.dyn'
        record_types:
          type:
          - string
          - 'null'
          description: '`*` or a comma-separated list of record types. Defaults to `*`.'
          example: A,AAAA,TXT
        tsig_key:
          type: string
          description: Name of an existing TSIG key.
          example: update-key
    ErrorResponse:
      type: object
      description: 'Generic error response: a plain description plus a machine-readable code.'
      required:
      - error
      - code
      properties:
        code:
          type: string
          example: ZONE_NOT_FOUND
        error:
          type: string
          example: Zone with name 'example.com' not found
    GetRecordResponse:
      type: object
      description: API representation of a record, optionally carrying its zone name.
      required:
      - id
      - name
      - record_type
      - value
      - ttl
      - zone_id
      properties:
        id:
          type: integer
          format: int32
          example: 1
        name:
          type: string
          example: sub
        priority:
          type:
          - integer
          - 'null'
          format: int32
          example: 10
        record_type:
          type: string
          example: A
        ttl:
          type: integer
          format: int32
          example: 3600
        value:
          $ref: '#/components/schemas/RecordValueRequest'
        zone_id:
          type: integer
          format: int32
          example: 1
        zone_name:
          type:
          - string
          - 'null'
          example: example.com
    GetTsigKeyResponse:
      type: object
      description: |-
        API representation of a TSIG key. `secret` is only present on create and
        single-key reads; list responses omit it.
      required:
      - id
      - name
      - algorithm
      - global
      - created_at
      properties:
        algorithm:
          type: string
          example: hmac-sha256
        created_at:
          type: string
          format: date-time
        global:
          type: boolean
          description: Whether the key may update every zone without any policy.
          example: false
        id:
          type: integer
          format: int32
          example: 1
        name:
          type: string
          example: update-key
        secret:
          type:
          - string
          - 'null'
          example: bXktMzItYnl0ZS1pbXBvcnQtc2VjcmV0LWV4YW1wbGU=
    GetZoneResponse:
      type: object
      description: API representation of a zone.
      required:
      - id
      - name
      - primary_ns
      - admin_email
      - ttl
      - refresh
      - retry
      - expire
      - minimum_ttl
      properties:
        admin_email:
          type: string
          example: admin@example.com
        expire:
          type: integer
          format: int32
          example: 604800
        id:
          type: integer
          format: int32
          example: 1
        minimum_ttl:
          type: integer
          format: int32
          example: 3600
        name:
          type: string
          example: example.com
        primary_ns:
          type: string
          example: ns1.example.com
        refresh:
          type: integer
          format: int32
          example: 7200
        retry:
          type: integer
          format: int32
          example: 3600
        serial:
          type:
          - integer
          - 'null'
          format: int32
          example: 42
        ttl:
          type: integer
          format: int32
          example: 3600
    GetZoneTsigPolicyResponse:
      type: object
      description: API representation of a zone TSIG policy.
      required:
      - id
      - tsig_key
      - record_name_pattern
      - record_types
      - created_at
      properties:
        created_at:
          type: string
          format: date-time
        id:
          type: integer
          format: int32
          example: 1
        record_name_pattern:
          type: string
          example: '*.dyn'
        record_types:
          type: string
          example: A,AAAA,TXT
        tsig_key:
          type: string
          example: update-key
    HealthResponse:
      type: object
      description: Health probe response.
      required:
      - status
      properties:
        status:
          type: string
          example: healthy
    ImportMode:
      type: string
      description: How parsed records are reconciled with the records already in the zone.
      enum:
      - append
      - upsert
      - replace
    ImportSummary:
      type: object
      description: |-
        Counts of records parsed, added, deleted, updated, unchanged, and skipped
        during import. `updated` is a TTL-only reconcile and is never also counted
        as `unchanged`.
      required:
      - parsed
      - added
      - deleted
      - updated
      - unchanged
      - skipped
      properties:
        added:
          type: integer
          example: 8
          minimum: 0
        deleted:
          type: integer
          example: 2
          minimum: 0
        parsed:
          type: integer
          example: 12
          minimum: 0
        skipped:
          type: integer
          example: 0
          minimum: 0
        unchanged:
          type: integer
          example: 2
          minimum: 0
        updated:
          type: integer
          example: 1
          minimum: 0
    ImportZoneFileRequest:
      type: object
      description: Request body for importing a BIND zone file into a zone.
      required:
      - content
      properties:
        content:
          type: string
          description: Raw BIND zone file text.
          example: |
            www IN A 192.0.2.1
            mail IN A 192.0.2.2
        dry_run:
          type: boolean
          description: When true, parse and validate without applying any change.
        mode:
          $ref: '#/components/schemas/ImportMode'
    ImportZoneFileResponse:
      type: object
      description: Result of a zone-file import, including a summary and any validation errors.
      required:
      - applied
      - dry_run
      - summary
      - diff
      - errors
      properties:
        applied:
          type: boolean
          example: true
        diff:
          $ref: '#/components/schemas/RecordDiff'
          description: The reconcile as a record diff, for previewing the change.
        dry_run:
          type: boolean
          example: false
        errors:
          type: array
          items:
            type: string
          description: Per-record validation errors. When non-empty nothing is applied.
        summary:
          $ref: '#/components/schemas/ImportSummary'
    MessageResponse:
      type: object
      description: Generic success message response.
      required:
      - message
      properties:
        message:
          type: string
          example: Deleted successfully
    NotifyZoneRequest:
      type: object
      description: Request body for triggering a NOTIFY, optionally scoped to one zone.
      properties:
        force:
          type: boolean
          example: true
        zone_name:
          type:
          - string
          - 'null'
          example: example.com
    Pagination:
      type: object
      description: Pagination window and total count for a list response.
      required:
      - limit
      - offset
      - total
      properties:
        limit:
          type: integer
          format: int32
          example: 50
          minimum: 0
        offset:
          type: integer
          format: int64
          example: 0
          minimum: 0
        total:
          type: integer
          format: int64
          example: 125
          minimum: 0
    RecordDiff:
      type: object
      description: |-
        A record-level difference between two record sets, RRset by RRset. Empty on
        a real apply, which does not need it; populated only for a dry-run preview.
      required:
      - entries
      - summary
      properties:
        entries:
          type: array
          items:
            $ref: '#/components/schemas/RecordDiffEntry'
        summary:
          $ref: '#/components/schemas/RecordDiffSummary'
    RecordDiffEntry:
      type: object
      description: |-
        One RRset (owner name + type) whose records differ, with the records present
        on each side. `from` is empty for `added`, `to` for `removed`.
      required:
      - change
      - name
      - record_type
      - from
      - to
      properties:
        change:
          type: string
          description: '`added`, `removed`, or `changed`.'
          example: changed
        from:
          type: array
          items:
            $ref: '#/components/schemas/RecordDiffValue'
        name:
          type: string
          example: www.example.com.
        record_type:
          type: string
          example: A
        to:
          type: array
          items:
            $ref: '#/components/schemas/RecordDiffValue'
    RecordDiffSummary:
      type: object
      description: How many RRsets were added, removed, and changed.
      required:
      - added
      - removed
      - changed
      properties:
        added:
          type: integer
          example: 1
          minimum: 0
        changed:
          type: integer
          example: 1
          minimum: 0
        removed:
          type: integer
          example: 1
          minimum: 0
    RecordDiffValue:
      type: object
      description: |-
        One record on one side of a diff. Rendering (zone-file rdata, priority
        placement) is left to the client; the value is in display form.
      required:
      - value
      - ttl
      properties:
        priority:
          type:
          - integer
          - 'null'
          format: int32
          example: 10
        ttl:
          type: integer
          format: int32
          example: 300
        value:
          $ref: '#/components/schemas/RecordValueRequest'
    RecordListResponse:
      type: object
      description: Paginated list of records.
      required:
      - items
      - pagination
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/GetRecordResponse'
        pagination:
          $ref: '#/components/schemas/Pagination'
    RecordResponse:
      type: object
      description: A single record wrapped in a response envelope.
      required:
      - record
      properties:
        record:
          $ref: '#/components/schemas/GetRecordResponse'
    RecordValueRequest:
      oneOf:
      - type: string
        example: 192.168.1.100
      - type: array
        items:
          type: string
        example:
        - hello
        - world
      description: 'A record value as sent by the client: a single string or TXT segments.'
    RollbackSummary:
      type: object
      description: |-
        Counts of what a rollback changes. TTL-only differences count as one
        delete plus one add.
      required:
      - records_added
      - records_deleted
      - records_unchanged
      - soa_changed
      properties:
        records_added:
          type: integer
          example: 2
          minimum: 0
        records_deleted:
          type: integer
          example: 3
          minimum: 0
        records_unchanged:
          type: integer
          example: 5
          minimum: 0
        soa_changed:
          type: boolean
          example: true
    RollbackZoneRequest:
      type: object
      description: Request body for rolling a zone back to a snapshot serial.
      required:
      - serial
      properties:
        dry_run:
          type: boolean
          description: When true, compute and report the rollback without applying any change.
        serial:
          type: integer
          format: int32
          example: 7
    RollbackZoneResponse:
      type: object
      description: |-
        Result of a zone rollback. The zone's state returns to `target_serial`
        while its serial advances to `new_serial` (serials never go backward).
      required:
      - applied
      - dry_run
      - target_serial
      - new_serial
      - summary
      properties:
        applied:
          type: boolean
          example: true
        dry_run:
          type: boolean
          example: false
        new_serial:
          type: integer
          format: int32
          example: 13
        summary:
          $ref: '#/components/schemas/RollbackSummary'
        target_serial:
          type: integer
          format: int32
          example: 7
    SecondaryStatusResponse:
      type: object
      description: Sync state of one configured secondary for a zone.
      required:
      - address
      - status
      properties:
        address:
          type: string
          example: 10.0.1.10:53
        error:
          type:
          - string
          - 'null'
        status:
          type: string
          description: '`in_sync` | `lagging` | `ahead` | `unreachable`'
          example: in_sync
        visible_serial:
          type:
          - integer
          - 'null'
          format: int64
          example: 42
    SnapshotDetailResponse:
      type: object
      description: One snapshot plus the reconstructed record set at that serial.
      required:
      - snapshot
      - records
      properties:
        records:
          type: array
          items:
            $ref: '#/components/schemas/SnapshotRecordResponse'
        snapshot:
          $ref: '#/components/schemas/ZoneSnapshotResponse'
    SnapshotDiffResponse:
      type: object
      description: The difference between two of a zone's serials.
      required:
      - from_serial
      - to_serial
      - diff
      properties:
        diff:
          $ref: '#/components/schemas/RecordDiff'
        from_serial:
          type: integer
          format: int32
          example: 41
        to_serial:
          type: integer
          format: int32
          example: 42
    SnapshotListResponse:
      type: object
      description: A page of zone snapshots.
      required:
      - items
      - pagination
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/ZoneSnapshotResponse'
        pagination:
          $ref: '#/components/schemas/Pagination'
    SnapshotRecordResponse:
      type: object
      description: |-
        A record reconstructed from the zone's change history; unlike stored
        records it has no database id.
      required:
      - name
      - record_type
      - value
      - ttl
      properties:
        name:
          type: string
          example: www
        priority:
          type:
          - integer
          - 'null'
          format: int32
          example: 10
        record_type:
          type: string
          example: A
        ttl:
          type: integer
          format: int32
          example: 3600
        value:
          $ref: '#/components/schemas/RecordValueRequest'
    TsigKeyListResponse:
      type: object
      description: List of TSIG keys (secrets omitted).
      required:
      - tsig_keys
      properties:
        tsig_keys:
          type: array
          items:
            $ref: '#/components/schemas/GetTsigKeyResponse'
    TsigKeyResponse:
      type: object
      description: A single TSIG key wrapped in a response envelope.
      required:
      - tsig_key
      properties:
        tsig_key:
          $ref: '#/components/schemas/GetTsigKeyResponse'
    UpdateRecordRequest:
      type: object
      description: Request body for updating an existing record.
      required:
      - name
      - record_type
      - value
      properties:
        name:
          type: string
          example: sub
        priority:
          type:
          - integer
          - 'null'
          format: int32
          description: MX and SRV priority, set here rather than inline in the value; other record types reject it.
          example: 10
        record_type:
          type: string
          example: A
        ttl:
          type:
          - integer
          - 'null'
          format: int32
          description: Optional; an omitted TTL is fixed to the zone's TTL at write time. Every record of an RRset (same name and type) must share one TTL.
          example: 3600
        value:
          $ref: '#/components/schemas/RecordValueRequest'
    ZoneDetailResponse:
      type: object
      description: A zone together with all of its records.
      required:
      - zone
      - records
      properties:
        records:
          type: array
          items:
            $ref: '#/components/schemas/GetRecordResponse'
        zone:
          $ref: '#/components/schemas/GetZoneResponse'
    ZoneListResponse:
      type: object
      description: Paginated list of zones.
      required:
      - items
      - pagination
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/GetZoneResponse'
        pagination:
          $ref: '#/components/schemas/Pagination'
    ZoneResponse:
      type: object
      description: A single zone wrapped in a response envelope.
      required:
      - zone
      properties:
        zone:
          $ref: '#/components/schemas/GetZoneResponse'
    ZoneSnapshotResponse:
      type: object
      description: |-
        One entry of a zone's serial history, with SOA metadata in API form
        (`admin_email` converted back from SOA mailbox form).
      required:
      - serial
      - primary_ns
      - admin_email
      - ttl
      - refresh
      - retry
      - expire
      - minimum_ttl
      - created_at
      properties:
        admin_email:
          type: string
          example: admin@example.com
        created_at:
          type: string
          format: date-time
        expire:
          type: integer
          format: int32
          example: 604800
        minimum_ttl:
          type: integer
          format: int32
          example: 3600
        primary_ns:
          type: string
          example: ns1.example.com
        refresh:
          type: integer
          format: int32
          example: 7200
        retry:
          type: integer
          format: int32
          example: 3600
        serial:
          type: integer
          format: int32
          example: 7
        ttl:
          type: integer
          format: int32
          example: 3600
    ZoneStatusResponse:
      type: object
      description: |-
        A zone's serial and the sync state of every configured secondary, probed
        live via SOA queries.
      required:
      - zone
      - serial
      - secondaries
      properties:
        secondaries:
          type: array
          items:
            $ref: '#/components/schemas/SecondaryStatusResponse'
        serial:
          type: integer
          format: int32
          example: 42
        zone:
          type: string
          example: example.com
    ZoneTsigPolicyListResponse:
      type: object
      description: List of a zone's TSIG policies.
      required:
      - tsig_policies
      properties:
        tsig_policies:
          type: array
          items:
            $ref: '#/components/schemas/GetZoneTsigPolicyResponse'
    ZoneTsigPolicyResponse:
      type: object
      description: A single zone TSIG policy wrapped in a response envelope.
      required:
      - tsig_policy
      properties:
        tsig_policy:
          $ref: '#/components/schemas/GetZoneTsigPolicyResponse'
  securitySchemes:
    bearer_auth:
      type: http
      scheme: bearer
tags:
- name: Health
  description: Service health probe for load balancers and orchestrators.
- name: Zone
  description: Manage DNS zones including creation, update, deletion, and retrieval.
- name: Record
  description: Manage DNS records including creation, update, deletion, and retrieval.
- name: Notify
  description: Send DNS NOTIFY messages to secondary servers.
- name: TSIG
  description: Manage TSIG keys and per-zone TSIG policies for nsupdate authentication.
