{
  "openapi": "3.1.0",
  "info": {
    "title": "Toyroom API",
    "version": "v1 (beta)",
    "description": "Domain intelligence from toyroom.ai. Full docs in markdown: https://api.toyroom.ai/llms-full.txt. MCP server: https://api.toyroom.ai/mcp.",
    "contact": {
      "email": "feedback@toyroom.ai"
    }
  },
  "servers": [
    {
      "url": "https://api.toyroom.ai"
    }
  ],
  "tags": [
    {
      "name": "Appraisal"
    },
    {
      "name": "Classification"
    },
    {
      "name": "Zone data"
    },
    {
      "name": "Lookups"
    },
    {
      "name": "Jobs"
    },
    {
      "name": "Account"
    }
  ],
  "security": [
    {
      "bearerKey": []
    }
  ],
  "paths": {
    "/v1/appraise": {
      "post": {
        "operationId": "appraise",
        "summary": "Appraise a domain",
        "description": "Returns a calibrated USD estimate with a low and high range, the word split and industry classification that fed the valuation, and how many extensions the same second-level name is registered under.\n\nCost: 1 credit. Rate limit: 30 requests/min.",
        "tags": [
          "Appraisal"
        ],
        "security": [
          {
            "bearerKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "domain": "cloudkitchen.com",
                  "final": {
                    "value": 24852.56,
                    "low": 14564.18,
                    "high": 24852.56,
                    "version": "v2.1 (calibrated)"
                  },
                  "classification": {
                    "split": "Cloud Kitchen",
                    "vertical": "Food & Beverage",
                    "subcategory": "Delivery & Catering",
                    "domain_type": "industry"
                  },
                  "zone": {
                    "indexed": true,
                    "exact_count": 72
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooMany"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "502": {
            "$ref": "#/components/responses/Upstream"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "domain": {
                    "type": "string",
                    "description": "One domain, e.g. cloudkitchen.com."
                  }
                },
                "required": [
                  "domain"
                ],
                "additionalProperties": false
              },
              "example": {
                "domain": "cloudkitchen.com"
              }
            }
          }
        }
      }
    },
    "/v1/appraise/bulk": {
      "post": {
        "operationId": "appraise_bulk",
        "summary": "Appraise a list",
        "description": "Same model as the single-domain call, one row per domain. Use it for portfolio triage.\n\nCost: 1 credit per domain. Rate limit: 6 requests/min. Batch max: 500 domains.",
        "tags": [
          "Appraisal"
        ],
        "security": [
          {
            "bearerKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "results": [
                    {
                      "domain": "solarfarm.io",
                      "value": 2033.72,
                      "low": 135.58,
                      "high": 2033.72,
                      "version": "v2.1 (calibrated)",
                      "classification": {
                        "split": "Solar Farm",
                        "vertical": "Industrial & Energy",
                        "subcategory": "Energy & Utilities",
                        "domain_type": "industry"
                      }
                    },
                    {
                      "domain": "aitrader.net",
                      "value": 329.12,
                      "low": 87.52,
                      "high": 4936.8,
                      "version": "v2.1 (calibrated)",
                      "classification": {
                        "split": "AI Trader",
                        "vertical": "Technology",
                        "subcategory": "AI & Machine Learning",
                        "domain_type": "industry"
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooMany"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "502": {
            "$ref": "#/components/responses/Upstream"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "domains": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Up to 500 domains.",
                    "maxItems": 500,
                    "minItems": 1
                  }
                },
                "required": [
                  "domains"
                ],
                "additionalProperties": false
              },
              "example": {
                "domains": [
                  "solarfarm.io",
                  "aitrader.net"
                ]
              }
            }
          }
        }
      }
    },
    "/v1/categorize": {
      "post": {
        "operationId": "categorize",
        "summary": "Categorize domains",
        "description": "Deterministic classification from a curated keyword lexicon and domain-type rules. Every result carries the matched keywords, a confidence level, secondary tags, and a domain type (industry, brandable, geo, and so on). No language model is involved, so the same input always returns the same answer.\n\nCost: 2 credits per domain. Rate limit: 12 requests/min. Batch max: 100 domains.",
        "tags": [
          "Classification"
        ],
        "security": [
          {
            "bearerKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "results": [
                    {
                      "domain": "cloudkitchen.com",
                      "sld": "cloudkitchen",
                      "split": "Cloud Kitchen",
                      "vertical": "Food & Beverage",
                      "subcategory": "Delivery & Catering",
                      "confidence": "high",
                      "matched": [
                        "cloud",
                        "kitchen",
                        "cloudkitchen"
                      ],
                      "source": "lexicon",
                      "type": "industry",
                      "tags": [
                        {
                          "vertical": "Technology",
                          "subcategory": "Data & Cloud"
                        }
                      ]
                    }
                  ],
                  "summary": {
                    "total": 2,
                    "categorized": 2,
                    "uncategorized": 0,
                    "verticals": [
                      {
                        "vertical": "Food & Beverage",
                        "count": 1
                      },
                      {
                        "vertical": "Technology",
                        "count": 1
                      }
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooMany"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "502": {
            "$ref": "#/components/responses/Upstream"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "domains": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Up to 100 domains.",
                    "maxItems": 100,
                    "minItems": 1
                  }
                },
                "required": [
                  "domains"
                ],
                "additionalProperties": false
              },
              "example": {
                "domains": [
                  "cloudkitchen.com",
                  "aitrader.io"
                ]
              }
            }
          }
        }
      }
    },
    "/v1/camelcase": {
      "post": {
        "operationId": "camelcase",
        "summary": "Split words",
        "description": "Dictionary-driven splitting with per-domain confidence, plus word, length, and extension statistics for the whole batch. One credit covers the entire request.\n\nCost: 1 credit. Rate limit: 60 requests/min. Batch max: 1000 domains.",
        "tags": [
          "Classification"
        ],
        "security": [
          {
            "bearerKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "results": [
                    {
                      "original": "cloudkitchen.com",
                      "converted": "CloudKitchen.com",
                      "split": "Cloud Kitchen",
                      "word_count": 2,
                      "confidence": "HIGH",
                      "category": "Food & Beverage",
                      "subcategory": "Delivery & Catering",
                      "domain_type": "industry"
                    }
                  ],
                  "word_stats": [
                    {
                      "word": "cloud",
                      "count": 1
                    },
                    {
                      "word": "kitchen",
                      "count": 1
                    }
                  ],
                  "tld_stats": [
                    {
                      "tld": "com",
                      "count": 1
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooMany"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "502": {
            "$ref": "#/components/responses/Upstream"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "domains": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Up to 1,000 domains.",
                    "maxItems": 1000,
                    "minItems": 1
                  }
                },
                "required": [
                  "domains"
                ],
                "additionalProperties": false
              },
              "example": {
                "domains": [
                  "cloudkitchen.com",
                  "solarfarm.io"
                ]
              }
            }
          }
        }
      }
    },
    "/v1/zone/count": {
      "post": {
        "operationId": "zone_count",
        "summary": "Count a keyword",
        "description": "Searches the Toyroom zone index: 390M+ registered domains across 23,000+ extensions, rebuilt from daily zone-file snapshots. Returns totals and a per-extension breakdown. Counts only: this endpoint never returns domain names, and that is a product boundary, not a missing feature.\n\nCost: 2 credits. Rate limit: 20 requests/min.",
        "tags": [
          "Zone data"
        ],
        "security": [
          {
            "bearerKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "term": "solar",
                  "position": "contains",
                  "total_matches": 156704,
                  "tld_match_count": 9432,
                  "exact_domain_count": 2,
                  "keyword_count": 155748,
                  "tld_breakdown": [
                    {
                      "tld": "com",
                      "count": 155701
                    },
                    {
                      "tld": "io",
                      "count": 1003
                    }
                  ],
                  "total_domains_in_db": 391652800
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooMany"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "502": {
            "$ref": "#/components/responses/Upstream"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "term": {
                    "type": "string",
                    "description": "Keyword, 2 to 63 characters, letters, digits, and hyphens.",
                    "minLength": 2,
                    "maxLength": 63,
                    "pattern": "^[a-z0-9-]+$"
                  },
                  "tlds": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Restrict the breakdown to these extensions, up to 50. Omit for all.",
                    "maxItems": 50
                  },
                  "position": {
                    "type": "string",
                    "description": "contains (default), starts, or ends.",
                    "enum": [
                      "contains",
                      "starts",
                      "ends"
                    ],
                    "default": "contains"
                  }
                },
                "required": [
                  "term"
                ],
                "additionalProperties": false
              },
              "example": {
                "term": "solar",
                "tlds": [
                  "com",
                  "io"
                ],
                "position": "contains"
              }
            }
          }
        }
      }
    },
    "/v1/zone/lookup": {
      "post": {
        "operationId": "zone_lookup",
        "summary": "Look up a list of names",
        "description": "The bulk form of the Zone Counter. Send full domains or bare names. For each one you get whether that exact domain is in the index and how many extensions the name is registered under. Add include_counts to also get how many registered domains contain, start with, or end with the name (slower, and doubles the cost). Rows come back in input order. Counts and booleans only: no domain names are ever returned.\n\nCost: 1 credit per 10 names. Rate limit: 12 requests/min. Batch max: 5000 domains.",
        "tags": [
          "Zone data"
        ],
        "security": [
          {
            "bearerKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "results": [
                    {
                      "input": "cloudkitchen.com",
                      "name": "cloudkitchen",
                      "extension": "com",
                      "registered": true,
                      "extensions_registered": 72
                    },
                    {
                      "input": "solarfarm.io",
                      "name": "solarfarm",
                      "extension": "io",
                      "registered": true,
                      "extensions_registered": 41
                    },
                    {
                      "input": "zqxjv.net",
                      "name": "zqxjv",
                      "extension": "net",
                      "registered": false,
                      "extensions_registered": 0
                    }
                  ],
                  "index_built_at": "2026-09-15T04:27:31Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooMany"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "502": {
            "$ref": "#/components/responses/Upstream"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "domains": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Up to 5,000 domains or bare names. The first label is the name, the rest is the extension.",
                    "maxItems": 5000,
                    "minItems": 1
                  },
                  "include_counts": {
                    "type": "boolean",
                    "description": "Add containing, starting, and ending counts per name. Doubles the cost."
                  }
                },
                "required": [
                  "domains"
                ],
                "additionalProperties": false
              },
              "example": {
                "domains": [
                  "cloudkitchen.com",
                  "solarfarm.io",
                  "zqxjv.net"
                ],
                "include_counts": false
              }
            }
          }
        }
      }
    },
    "/v1/zone/stats": {
      "get": {
        "operationId": "zone_stats",
        "summary": "Index snapshot",
        "description": "Use it to cite the exact index size and build time next to any count you publish.\n\nCost: 1 credit. Rate limit: 20 requests/min.",
        "tags": [
          "Zone data"
        ],
        "security": [
          {
            "bearerKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "built_at": "2026-09-15T04:27:31Z",
                  "total_domains": 391652800,
                  "total_slds": 256425219,
                  "total_tlds": 23533,
                  "top_tlds": [
                    {
                      "tld": "com",
                      "count": 167894670
                    },
                    {
                      "tld": "de",
                      "count": 17895018
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooMany"
          }
        }
      }
    },
    "/v1/rdap": {
      "post": {
        "operationId": "rdap",
        "summary": "Registration data",
        "description": "Resolves any extension through the IANA RDAP bootstrap, with WHOIS fallback where a registry has no RDAP service. Registries enforce hard global rate caps that every client shares, so this is the tightest limit on the platform. Registration data changes slowly: cache what you fetch.\n\nCost: 2 credits per domain. Rate limit: 6 requests/min. Batch max: 10 domains.",
        "tags": [
          "Lookups"
        ],
        "security": [
          {
            "bearerKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "results": [
                    {
                      "domain": "google.com",
                      "status": "found",
                      "registrationDate": "1997-09-15T04:00:00.000Z",
                      "expirationDate": "2028-09-14T04:00:00.000Z",
                      "lastUpdatedDate": "2026-09-15T18:23:54.000Z",
                      "registrar": "MarkMonitor Inc.",
                      "age": "29 years",
                      "statusFlags": [
                        "client delete prohibited",
                        "client transfer prohibited"
                      ],
                      "nameservers": [
                        "NS1.GOOGLE.COM",
                        "NS2.GOOGLE.COM"
                      ],
                      "dnssecEnabled": false
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooMany"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "502": {
            "$ref": "#/components/responses/Upstream"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "domains": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Up to 10 domains.",
                    "maxItems": 10,
                    "minItems": 1
                  }
                },
                "required": [
                  "domains"
                ],
                "additionalProperties": false
              },
              "example": {
                "domains": [
                  "google.com"
                ]
              }
            }
          }
        }
      }
    },
    "/v1/dns": {
      "post": {
        "operationId": "dns",
        "summary": "DNS records",
        "description": "Resolves against public resolvers. Choose record types with record_types; the default set is A, AAAA, MX, TXT, NS.\n\nCost: 1 credit per domain. Rate limit: 12 requests/min. Batch max: 50 domains.",
        "tags": [
          "Lookups"
        ],
        "security": [
          {
            "bearerKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "results": {
                    "google.com": {
                      "A": [
                        "142.251.14.102",
                        "142.251.14.101"
                      ],
                      "MX": [
                        {
                          "exchange": "smtp.google.com",
                          "priority": 10
                        }
                      ],
                      "errors": []
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooMany"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "502": {
            "$ref": "#/components/responses/Upstream"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "domains": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Up to 50 domains.",
                    "maxItems": 50,
                    "minItems": 1
                  },
                  "record_types": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "A",
                        "AAAA",
                        "MX",
                        "TXT",
                        "NS",
                        "CNAME",
                        "SOA"
                      ]
                    },
                    "description": "Any of A, AAAA, MX, TXT, NS, CNAME, SOA.",
                    "default": [
                      "A",
                      "AAAA",
                      "MX",
                      "TXT",
                      "NS"
                    ]
                  }
                },
                "required": [
                  "domains"
                ],
                "additionalProperties": false
              },
              "example": {
                "domains": [
                  "google.com"
                ],
                "record_types": [
                  "A",
                  "MX"
                ]
              }
            }
          }
        }
      }
    },
    "/v1/jobs": {
      "post": {
        "operationId": "job_create",
        "summary": "Submit a job",
        "description": "Send the list once and let Toyroom do the batching. The body is a JSON object, or a plain text file with one name per line (Content-Type: text/plain, type and options in the query string), either optionally gzip-encoded (Content-Encoding: gzip, 32 MB max). Credits for the whole job are reserved when it is accepted and refunded for every row that is never processed. Give a callback_url to be told when it finishes; poll otherwise.\n\nCost: reserved at submit. Rate limit: 12 requests/min.",
        "tags": [
          "Jobs"
        ],
        "security": [
          {
            "bearerKey": []
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted",
            "content": {
              "application/json": {
                "example": {
                  "id": "job_9f1c2a7d0b3e4f5a6b7c8d9e",
                  "type": "zone_lookup",
                  "status": "queued",
                  "total": 3,
                  "done": 0,
                  "errors": 0,
                  "progress": 0.0,
                  "options": {
                    "include_counts": false
                  },
                  "credits_reserved": 1,
                  "credits_refunded": 0,
                  "credits_charged": 1,
                  "position": 1,
                  "created": "2026-09-16T10:03:12Z",
                  "estimated_start": "2026-09-16T10:03:12Z",
                  "estimated_finish": "2026-09-16T10:03:13Z",
                  "deadline": "2026-09-16T12:03:12Z",
                  "started": null,
                  "finished": null,
                  "expires_at": null,
                  "partial": false,
                  "poll_url": "/v1/jobs/job_9f1c2a7d0b3e4f5a6b7c8d9e",
                  "results_url": null,
                  "callback": {
                    "url": "https://client.example/hooks/toyroom",
                    "status": "pending",
                    "attempts": 0,
                    "last_error": null
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooMany"
          },
          "503": {
            "description": "Queue full: estimated_wait_seconds and Retry-After say when to try again. Nothing charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "502": {
            "$ref": "#/components/responses/Upstream"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "description": "zone_lookup, appraise, or categorize."
                  },
                  "domains": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Up to 1,000,000 names. Validated like the matching endpoint; the first bad entry rejects the whole submission."
                  },
                  "options": {
                    "type": "object",
                    "description": "zone_lookup accepts include_counts (boolean). Other types take none."
                  },
                  "callback_url": {
                    "type": "string",
                    "description": "HTTPS URL to POST a signed notice to when the job reaches a final state."
                  },
                  "idempotency_key": {
                    "type": "string",
                    "description": "Resubmitting with the same key within 24 hours returns the existing job instead of creating another."
                  }
                },
                "required": [
                  "type",
                  "domains"
                ],
                "additionalProperties": false
              },
              "example": {
                "type": "zone_lookup",
                "options": {
                  "include_counts": false
                },
                "domains": [
                  "cloudkitchen.com",
                  "solarfarm.io",
                  "zqxjv.net"
                ],
                "callback_url": "https://client.example/hooks/toyroom",
                "idempotency_key": "portfolio-2026-09-16"
              }
            }
          }
        }
      },
      "get": {
        "operationId": "job_list",
        "summary": "List jobs",
        "description": "Newest first. Expired jobs stay listed for a day after their files are removed.\n\nCost: free. Not rate limited.",
        "tags": [
          "Jobs"
        ],
        "security": [
          {
            "bearerKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "jobs": [
                    {
                      "id": "job_9f1c2a7d0b3e4f5a6b7c8d9e",
                      "type": "zone_lookup",
                      "status": "succeeded",
                      "total": 1000000,
                      "done": 1000000,
                      "errors": 0,
                      "progress": 1.0,
                      "results_url": "/v1/jobs/job_9f1c2a7d0b3e4f5a6b7c8d9e/results",
                      "expires_at": "2026-09-17T10:20:41Z"
                    }
                  ],
                  "names_in_flight": 0
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooMany"
          }
        }
      }
    },
    "/v1/jobs/{job_id}": {
      "get": {
        "operationId": "job_status",
        "summary": "Check a job",
        "description": "Free and not rate limited. While queued or running the response carries Retry-After: 30, a sensible polling interval.\n\nCost: free. Not rate limited.",
        "tags": [
          "Jobs"
        ],
        "security": [
          {
            "bearerKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "id": "job_9f1c2a7d0b3e4f5a6b7c8d9e",
                  "type": "zone_lookup",
                  "status": "running",
                  "total": 1000000,
                  "done": 415000,
                  "errors": 0,
                  "progress": 0.415,
                  "options": {
                    "include_counts": false
                  },
                  "credits_reserved": 100000,
                  "credits_refunded": 0,
                  "credits_charged": 100000,
                  "created": "2026-09-16T10:03:12Z",
                  "estimated_start": null,
                  "estimated_finish": "2026-09-16T10:20:41Z",
                  "deadline": null,
                  "started": "2026-09-16T10:04:02Z",
                  "finished": null,
                  "expires_at": null,
                  "partial": false,
                  "poll_url": "/v1/jobs/job_9f1c2a7d0b3e4f5a6b7c8d9e",
                  "results_url": null
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooMany"
          },
          "404": {
            "description": "No such job for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      },
      "delete": {
        "operationId": "job_cancel",
        "summary": "Cancel or delete a job",
        "description": "A queued job is cancelled at once and fully refunded. A running job stops after its current chunk, keeps the rows it wrote (downloadable), and refunds the rest. A finished job has its file deleted now instead of at expiry.\n\nCost: free. Not rate limited.",
        "tags": [
          "Jobs"
        ],
        "security": [
          {
            "bearerKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "id": "job_9f1c2a7d0b3e4f5a6b7c8d9e",
                  "type": "zone_lookup",
                  "status": "cancelled",
                  "total": 1000000,
                  "done": 415000,
                  "errors": 0,
                  "progress": 0.415,
                  "credits_reserved": 100000,
                  "credits_refunded": 58500,
                  "credits_charged": 41500,
                  "results_url": "/v1/jobs/job_9f1c2a7d0b3e4f5a6b7c8d9e/results"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooMany"
          },
          "404": {
            "description": "No such job for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/v1/jobs/{job_id}/results": {
      "get": {
        "operationId": "job_results",
        "summary": "Download results",
        "description": "Streams the whole file. NDJSON is served gzip-encoded when the client accepts it. Add ?from=N to resume an NDJSON download at row N. A job that is still running or stopped early serves the rows it has, with X-Job-Partial: true. Files live 24 hours after the job finishes; after that the endpoint answers 410.\n\nCost: free. Not rate limited.",
        "tags": [
          "Jobs"
        ],
        "security": [
          {
            "bearerKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/x-ndjson": {
                "example": {
                  "input": "cloudkitchen.com",
                  "name": "cloudkitchen",
                  "extension": "com",
                  "registered": true,
                  "extensions_registered": 72,
                  "supported": true
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooMany"
          },
          "404": {
            "description": "No such job for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "No rows yet; poll the job.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "410": {
            "description": "Results expired (24 hours after finish).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "format",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "ndjson",
                "csv"
              ],
              "default": "ndjson"
            }
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0
            },
            "description": "Resume an NDJSON download at this row."
          }
        ]
      }
    },
    "/v1/usage": {
      "get": {
        "operationId": "usage",
        "summary": "Usage today",
        "description": "Free to call. Poll it to pace a long batch or to show a balance in your own tooling.\n\nCost: free. Not rate limited.",
        "tags": [
          "Account"
        ],
        "security": [
          {
            "bearerKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "key": "your-name",
                  "date": "2026-09-15",
                  "credits_used": 16,
                  "credits_remaining": 1984,
                  "daily_quota": 2000,
                  "resets_at": "2026-09-16T00:00:00Z",
                  "by_endpoint": {
                    "appraise": 2,
                    "zone": 6,
                    "categorize": 4,
                    "rdap": 2,
                    "dns": 1,
                    "camelcase": 1
                  },
                  "rate_limits_per_minute": {
                    "appraise": 30,
                    "appraise_bulk": 6,
                    "categorize": 12,
                    "camelcase": 60,
                    "zone": 20,
                    "zone_lookup": 12,
                    "jobs": 12,
                    "rdap": 6,
                    "dns": 12
                  },
                  "batch_limits": {
                    "appraise_bulk": 500,
                    "categorize": 100,
                    "camelcase": 1000,
                    "zone_lookup": 5000,
                    "rdap": 10,
                    "dns": 50
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooMany"
          }
        }
      }
    },
    "/v1/ping": {
      "get": {
        "operationId": "ping",
        "summary": "Check a key",
        "description": "Free to call and never rate limited. Use it in health checks.\n\nCost: free. Not rate limited.",
        "tags": [
          "Account"
        ],
        "security": [
          {
            "bearerKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "key": "your-name"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooMany"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key, e.g. trm_live_..."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "retry_after_seconds": {
            "type": "integer"
          },
          "resets_at": {
            "type": "string"
          }
        },
        "required": [
          "error"
        ]
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Invalid body: not JSON, missing field, list too long, or an item is not a domain.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing or invalid API key.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "TooMany": {
        "description": "Rate limit (per minute) or daily quota. Retry-After header in seconds.",
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Upstream": {
        "description": "The tool behind the endpoint did not answer. Nothing was charged; retry with backoff.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  }
}
