{
    "openapi": "3.1.0",
    "info": {
        "title": "Knov.ai Directory API",
        "version": "1.0.0",
        "summary": "Read the OARS-verified directory and submit a domain for verification.",
        "description": "The public, free Knov.ai Directory API. It lets agents browse and search the directory of businesses scored against OARS (the Open Agent Readiness Standard), read a single domain's verification status, and submit a domain for verification.\n\n## Authentication\nNone. This API exposes only public operations, so no API key or OAuth flow is required. Reads are open. The submit-for-verification write is also open to any caller; its protected effect \u2014 getting a domain verified or listed \u2014 is authorized out-of-band by a domain-ownership challenge (publish the returned token via oars.json, a /.well-known file, or a DNS TXT record), which binds authorization to control of the specific domain rather than to a caller account. OAuth 2.1 is therefore not applicable to this surface. Vulnerability disclosure: /.well-known/security.txt.\n\n## Versioning & deprecation\nThe API is versioned in the path (`/api/v1`). Additive, backward-compatible changes (new endpoints, new optional fields) ship within the current major version. Breaking changes ship under a new major path (`/api/v2`); the prior version is then supported for at least 6 months, during which responses carry a `Deprecation` header and a `Sunset` date (RFC 8594).\n\n## Idempotency\nMutating requests require a client-supplied `Idempotency-Key` header (any unique string; a UUID is recommended). A retried request with the same key returns the original response and performs no duplicate side effect. Keys are honored for 24 hours; reusing a key with a different body is a `409` `idempotency_conflict`.\n\n## Errors\nErrors use RFC 9457 Problem Details (`application/problem+json`) with a stable `code`, a `retryable` flag, and `Retry-After` on time-sensitive failures.\n\n## Long-running operations\nVerification is asynchronous: `POST /api/v1/verifications` returns `202` with an operation whose `statusUrl` is polled to a terminal state (`succeeded` or `failed`).",
        "termsOfService": "https://knov.ai/terms",
        "contact": {
            "name": "Knov.ai",
            "url": "https://knov.ai/api",
            "email": "support@knov.ai"
        },
        "license": {
            "name": "Open \u2014 free to use"
        },
        "x-oars-level": "3a-callable",
        "x-oars-version": "1.2"
    },
    "servers": [
        {
            "url": "https://knov.ai",
            "description": "Production"
        }
    ],
    "externalDocs": {
        "description": "Human-readable API reference",
        "url": "https://knov.ai/api"
    },
    "tags": [
        {
            "name": "Directory",
            "description": "Read the OARS-verified directory."
        },
        {
            "name": "Verification",
            "description": "Submit a domain for verification and track it."
        }
    ],
    "paths": {
        "/api/v1/directory": {
            "get": {
                "operationId": "listDirectory",
                "tags": [
                    "Directory"
                ],
                "summary": "List and search directory entities",
                "description": "Return listed directory entities, newest-verified first. All filters are optional and combine.",
                "parameters": [
                    {
                        "name": "q",
                        "in": "query",
                        "description": "Free-text match against name, description, categories, and manifest.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "level",
                        "in": "query",
                        "description": "Exact OARS level (1\u20135).",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 5
                        }
                    },
                    {
                        "name": "type",
                        "in": "query",
                        "description": "Entity type, e.g. \"Business\".",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "tier",
                        "in": "query",
                        "description": "Verification tier, or \"self\" for not-yet-verified entities.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "category",
                        "in": "query",
                        "description": "Industry/category label.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Page size (1\u2013200).",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 200,
                            "default": 50
                        }
                    },
                    {
                        "name": "offset",
                        "in": "query",
                        "description": "Number of results to skip.",
                        "schema": {
                            "type": "integer",
                            "minimum": 0,
                            "default": 0
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "A page of directory entities.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/DirectoryList"
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v1/directory/{domain}": {
            "get": {
                "operationId": "getDirectoryEntity",
                "tags": [
                    "Directory"
                ],
                "summary": "Get one domain with its verification status and manifest",
                "parameters": [
                    {
                        "name": "domain",
                        "in": "path",
                        "required": true,
                        "description": "The entity domain, e.g. \"example.com\".",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The entity, its verification status, and its published oars.json.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EntityDetail"
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v1/verifications": {
            "post": {
                "operationId": "submitVerification",
                "tags": [
                    "Verification"
                ],
                "summary": "Submit a domain for verification",
                "description": "Starts the verification flow: validates input, runs the automated pre-check, and returns an ownership challenge plus a long-running operation to poll. The submitter must publish the returned token (in oars.json, a /.well-known file, or a DNS TXT record) before a reviewer is engaged.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/IdempotencyKey"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/VerificationSubmit"
                            }
                        }
                    }
                },
                "responses": {
                    "202": {
                        "description": "Accepted. Returns the verification operation and the ownership challenge.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/VerificationOperation"
                                }
                            }
                        }
                    },
                    "200": {
                        "description": "The domain is already in the system; its current operation is returned.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/VerificationOperation"
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/BadRequest"
                    },
                    "409": {
                        "$ref": "#/components/responses/Conflict"
                    },
                    "422": {
                        "$ref": "#/components/responses/Unprocessable"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v1/verifications/{token}": {
            "get": {
                "operationId": "getVerification",
                "tags": [
                    "Verification"
                ],
                "summary": "Poll a verification operation",
                "description": "Resolve the status of a verification submission. Terminal states are `succeeded` and `failed`; while non-terminal, honor the `pollAfter` interval (and `Retry-After`).",
                "parameters": [
                    {
                        "name": "token",
                        "in": "path",
                        "required": true,
                        "description": "The operation id returned by submitVerification.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The verification operation and its current status.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/VerificationOperation"
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        }
    },
    "components": {
        "parameters": {
            "IdempotencyKey": {
                "name": "Idempotency-Key",
                "in": "header",
                "required": true,
                "description": "A unique client-supplied key (a UUID is recommended). Retries with the same key replay the original response. Honored for 24 hours.",
                "schema": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 255
                }
            }
        },
        "responses": {
            "NotFound": {
                "description": "No such resource.",
                "content": {
                    "application/problem+json": {
                        "schema": {
                            "$ref": "#/components/schemas/Problem"
                        }
                    }
                }
            },
            "BadRequest": {
                "description": "Malformed or missing input.",
                "content": {
                    "application/problem+json": {
                        "schema": {
                            "$ref": "#/components/schemas/Problem"
                        }
                    }
                }
            },
            "Conflict": {
                "description": "Idempotency-Key reused with a different payload, or an identical request is still in flight.",
                "content": {
                    "application/problem+json": {
                        "schema": {
                            "$ref": "#/components/schemas/Problem"
                        }
                    }
                }
            },
            "Unprocessable": {
                "description": "Input was well-formed but failed validation (e.g. unreachable URL).",
                "content": {
                    "application/problem+json": {
                        "schema": {
                            "$ref": "#/components/schemas/Problem"
                        }
                    }
                }
            },
            "RateLimited": {
                "description": "Rate limit exceeded. Honor the Retry-After header.",
                "headers": {
                    "Retry-After": {
                        "description": "Seconds to wait before retrying.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                },
                "content": {
                    "application/problem+json": {
                        "schema": {
                            "$ref": "#/components/schemas/Problem"
                        }
                    }
                }
            }
        },
        "schemas": {
            "Problem": {
                "type": "object",
                "description": "RFC 9457 Problem Details.",
                "properties": {
                    "type": {
                        "type": "string",
                        "format": "uri",
                        "description": "A URI identifying the problem type; dereferences to its docs entry."
                    },
                    "title": {
                        "type": "string"
                    },
                    "status": {
                        "type": "integer"
                    },
                    "code": {
                        "type": "string",
                        "description": "Stable machine-readable error code."
                    },
                    "detail": {
                        "type": "string"
                    },
                    "retryable": {
                        "type": "boolean",
                        "description": "Whether retrying the same request may succeed."
                    },
                    "retryAfter": {
                        "type": "integer",
                        "description": "Seconds to wait before retrying, when applicable."
                    },
                    "errors": {
                        "type": "object",
                        "additionalProperties": {
                            "type": "string"
                        },
                        "description": "Per-field validation messages."
                    }
                },
                "required": [
                    "type",
                    "title",
                    "status",
                    "code",
                    "retryable"
                ]
            },
            "VerificationBlock": {
                "type": "object",
                "properties": {
                    "verified": {
                        "type": "boolean"
                    },
                    "verificationStatus": {
                        "type": "string",
                        "description": "none | requested | in_review | verified | rejected | revoked"
                    },
                    "verificationTier": {
                        "type": "string"
                    },
                    "standing": {
                        "type": "string"
                    },
                    "oarsLevel": {
                        "type": "integer"
                    },
                    "oarsLevelLabel": {
                        "type": "string"
                    },
                    "listed": {
                        "type": "boolean"
                    },
                    "submittedAt": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "verifiedAt": {
                        "type": [
                            "string",
                            "null"
                        ]
                    }
                }
            },
            "DirectoryItem": {
                "type": "object",
                "properties": {
                    "domain": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "entityType": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "oarsLevel": {
                        "type": "integer"
                    },
                    "verified": {
                        "type": "boolean"
                    },
                    "verificationTier": {
                        "type": "string"
                    },
                    "categories": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "location": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "profileUrl": {
                        "type": "string",
                        "format": "uri"
                    }
                }
            },
            "DirectoryList": {
                "type": "object",
                "properties": {
                    "count": {
                        "type": "integer",
                        "description": "Number of results in this page."
                    },
                    "total": {
                        "type": "integer",
                        "description": "Total results matching the filters."
                    },
                    "limit": {
                        "type": "integer"
                    },
                    "offset": {
                        "type": "integer"
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/DirectoryItem"
                        }
                    }
                },
                "required": [
                    "count",
                    "total",
                    "limit",
                    "offset",
                    "results"
                ]
            },
            "EntityDetail": {
                "type": "object",
                "properties": {
                    "domain": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "entityType": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "description": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "categories": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "verification": {
                        "$ref": "#/components/schemas/VerificationBlock"
                    },
                    "profileUrl": {
                        "type": "string",
                        "format": "uri"
                    },
                    "manifest": {
                        "type": "object",
                        "description": "The entity's published oars.json, if any.",
                        "additionalProperties": true
                    }
                }
            },
            "VerificationSubmit": {
                "type": "object",
                "properties": {
                    "url": {
                        "type": "string",
                        "description": "The domain or URL to verify, e.g. \"example.com\"."
                    },
                    "contact_name": {
                        "type": "string"
                    },
                    "contact_email": {
                        "type": "string",
                        "format": "email"
                    },
                    "message": {
                        "type": "string",
                        "description": "Optional note to the reviewer."
                    },
                    "wants_listing": {
                        "type": "boolean",
                        "default": true,
                        "description": "List publicly in the directory once ownership is proven."
                    }
                },
                "required": [
                    "url",
                    "contact_name",
                    "contact_email"
                ]
            },
            "OwnershipMethod": {
                "type": "object",
                "properties": {
                    "label": {
                        "type": "string"
                    },
                    "how": {
                        "type": "string"
                    },
                    "snippet": {
                        "type": "string",
                        "description": "The exact value to publish."
                    },
                    "where": {
                        "type": "string",
                        "description": "Where to publish it."
                    }
                }
            },
            "VerificationOperation": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "Operation id (also the ownership token)."
                    },
                    "domain": {
                        "type": "string"
                    },
                    "status": {
                        "type": "string",
                        "description": "pending_ownership | in_review | succeeded | failed"
                    },
                    "terminal": {
                        "type": "boolean"
                    },
                    "statusUrl": {
                        "type": "string",
                        "format": "uri",
                        "description": "Poll this for status."
                    },
                    "pollAfter": {
                        "type": "integer",
                        "description": "Suggested seconds between polls while non-terminal."
                    },
                    "oarsLevel": {
                        "type": "integer",
                        "description": "Automated pre-check level."
                    },
                    "ownership": {
                        "type": "object",
                        "description": "Present while status is pending_ownership.",
                        "properties": {
                            "token": {
                                "type": "string"
                            },
                            "methods": {
                                "type": "object",
                                "additionalProperties": {
                                    "$ref": "#/components/schemas/OwnershipMethod"
                                }
                            }
                        }
                    }
                },
                "required": [
                    "id",
                    "domain",
                    "status",
                    "terminal",
                    "statusUrl"
                ]
            }
        }
    }
}