{
  "openapi": "3.1.0",
  "info": {
    "title": "Auditor IA API",
    "version": "1.0.0",
    "summary": "Audit B2B prospect lists before enrichment, CRM import or outreach.",
    "description": "Every record is classified process / review / verify / discard with reason codes.\n\n- `mode: \"sample\"` (default) is FREE: the first 250 records, never charges.\n- `mode: \"full\"` audits every record (up to 100,000) for 1 credit per record, charged once. It requires an `Idempotency-Key` header: retrying with the same key and file returns the same audit (`idempotent_replay: true`) and never charges again.\n\nAuthenticate with an account API key (`Authorization: Bearer aia_live_…`) created in Account → API keys. The same account, credits and audits are available on the web app and through the remote MCP server at `/mcp`.\n\nErrors always use `{\"error\": {\"code\": \"…\", \"message\": \"…\"}}`. Rate limits protect the service (bursts, concurrency) and never cap how many records you can audit.",
    "contact": {
      "url": "https://pilot.useauditoria.com/?legal=support"
    },
    "termsOfService": "https://pilot.useauditoria.com/?legal=terms"
  },
  "servers": [
    {
      "url": "https://pilot.useauditoria.com"
    }
  ],
  "security": [
    {
      "apiKey": []
    },
    {
      "oauth2": [
        "audit:read",
        "audit:write",
        "balance:read"
      ]
    }
  ],
  "tags": [
    {
      "name": "Audits"
    },
    {
      "name": "Account"
    }
  ],
  "paths": {
    "/api/v1/balance": {
      "get": {
        "tags": [
          "Account"
        ],
        "operationId": "getBalance",
        "summary": "Credit balance of the API key's account",
        "responses": {
          "200": {
            "description": "Balance",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Balance"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/audits/estimate": {
      "post": {
        "tags": [
          "Audits"
        ],
        "operationId": "estimateAudit",
        "summary": "Count records and quote the full-audit cost (never charges, never stores the file)",
        "requestBody": {
          "$ref": "#/components/requestBodies/AuditInput"
        },
        "responses": {
          "200": {
            "description": "Estimate",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Estimate"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "415": {
            "$ref": "#/components/responses/BadRequest"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/audits": {
      "post": {
        "tags": [
          "Audits"
        ],
        "operationId": "createAudit",
        "summary": "Audit a CSV (free sample or paid full audit)",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Required when mode is \"full\". 16-100 characters of [A-Za-z0-9_-]. Reuse the same key to retry safely; use a new key for a new operation.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{16,100}$"
            }
          }
        ],
        "requestBody": {
          "$ref": "#/components/requestBodies/AuditInput"
        },
        "responses": {
          "201": {
            "description": "Audit created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Audit"
                }
              }
            }
          },
          "200": {
            "description": "Idempotent replay of an earlier full audit made with the same Idempotency-Key and file (no new charge)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StoredAudit"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "description": "INSUFFICIENT_CREDITS — top up at top_up_url, or run the free sample",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "DESTINATION_NOT_FOUND",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "ALREADY_PROCESSED (this file was already audited in full; error.auditId), IN_PROGRESS, IDEMPOTENCY_KEY_REUSED (key used for different content) or IDEMPOTENCY_KEY_USED",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "415": {
            "$ref": "#/components/responses/BadRequest"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "BUSY — service capacity momentarily in use; retry after Retry-After seconds",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/audits/{id}": {
      "get": {
        "tags": [
          "Audits"
        ],
        "operationId": "getAudit",
        "summary": "A previous audit of this account",
        "parameters": [
          {
            "$ref": "#/components/parameters/AuditId"
          }
        ],
        "responses": {
          "200": {
            "description": "Audit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StoredAudit"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "AUDIT_NOT_FOUND",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/audits/{id}/annotated.csv": {
      "get": {
        "tags": [
          "Audits"
        ],
        "operationId": "downloadAnnotatedCsv",
        "summary": "Every audited row with its decision and reasons (kept 14 days)",
        "parameters": [
          {
            "$ref": "#/components/parameters/AuditId"
          }
        ],
        "responses": {
          "200": {
            "description": "Annotated CSV",
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "AUDIT_NOT_FOUND or ANNOTATED_CSV_NOT_AVAILABLE",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "410": {
            "description": "AUDIT_EXPIRED — deleted by the 14-day retention policy",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "aia_<live|test>_<id>_<secret>",
        "description": "Account API key from Account → API keys."
      },
      "oauth2": {
        "type": "oauth2",
        "description": "OAuth 2.1 authorization code with PKCE (S256), public clients registered dynamically (RFC 7591). Same account and credits as API keys.",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://pilot.useauditoria.com/oauth/authorize",
            "tokenUrl": "https://pilot.useauditoria.com/oauth/token",
            "refreshUrl": "https://pilot.useauditoria.com/oauth/token",
            "scopes": {
              "audit:read": "Read audits and estimate costs",
              "audit:write": "Run audits (full audits spend credits)",
              "balance:read": "Read the credit balance"
            }
          }
        }
      }
    },
    "parameters": {
      "AuditId": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      }
    },
    "requestBodies": {
      "AuditInput": {
        "required": true,
        "description": "The CSV (UTF-8, header row + records, up to 20 MB / 100,000 records) as JSON, multipart or a raw text/csv body (then pass the other fields as query parameters).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/AuditRequest"
            }
          },
          "multipart/form-data": {
            "schema": {
              "type": "object",
              "required": [
                "file"
              ],
              "properties": {
                "file": {
                  "type": "string",
                  "format": "binary"
                },
                "mode": {
                  "type": "string",
                  "enum": [
                    "sample",
                    "full"
                  ]
                },
                "max_credits": {
                  "type": "integer"
                },
                "rerun": {
                  "type": "boolean"
                },
                "destination_id": {
                  "type": "string"
                }
              }
            }
          },
          "text/csv": {
            "schema": {
              "type": "string"
            }
          }
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "INVALID_API_KEY — missing, invalid, revoked or wrong-mode key",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "RateLimited": {
        "description": "RATE_LIMITED — too many requests or concurrent audits for this key; honor Retry-After",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "BadRequest": {
        "description": "INVALID_CSV, CSV_REQUIRED, CSV_TOO_MANY_RECORDS, INVALID_MODE, INVALID_MAX_CREDITS, IDEMPOTENCY_KEY_REQUIRED, INVALID_JSON, UNSUPPORTED_MEDIA_TYPE …",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "TooLarge": {
        "description": "CSV_TOO_LARGE — over 20 MB",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unprocessable": {
        "description": "INVALID_ENCODING (not UTF-8), MAX_CREDITS_EXCEEDED or SPEND_GUARD_EXCEEDED (nothing charged)",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string",
                "examples": [
                  "INSUFFICIENT_CREDITS"
                ]
              },
              "message": {
                "type": "string"
              },
              "top_up_url": {
                "type": "string"
              },
              "cost": {
                "type": "integer"
              },
              "balance": {
                "type": "integer"
              },
              "auditId": {
                "type": "string"
              }
            },
            "additionalProperties": true
          }
        }
      },
      "AuditRequest": {
        "type": "object",
        "required": [
          "csv"
        ],
        "properties": {
          "csv": {
            "type": "string",
            "description": "CSV text (UTF-8)."
          },
          "file_name": {
            "type": "string"
          },
          "mode": {
            "type": "string",
            "enum": [
              "sample",
              "full"
            ],
            "default": "sample"
          },
          "max_credits": {
            "type": "integer",
            "minimum": 1,
            "description": "Full mode: refuse (nothing charged) if the audit would cost more."
          },
          "rerun": {
            "type": "boolean",
            "default": false,
            "description": "Full mode: re-audit a file already audited in full (new operation; needs a new Idempotency-Key)."
          },
          "destination_id": {
            "type": "string"
          }
        }
      },
      "Balance": {
        "type": "object",
        "properties": {
          "object": {
            "const": "balance"
          },
          "mode": {
            "type": "string",
            "enum": [
              "live",
              "test"
            ]
          },
          "balance_credits": {
            "type": "integer"
          },
          "credit_unit": {
            "const": "record"
          },
          "full_audit_cost_per_record": {
            "type": "integer"
          },
          "free_sample_records": {
            "type": "integer"
          },
          "api_key": {
            "type": "object",
            "properties": {
              "daily_credit_limit": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "spent_last_24h": {
                "type": "integer"
              }
            }
          },
          "top_up_url": {
            "type": "string"
          }
        }
      },
      "Estimate": {
        "type": "object",
        "properties": {
          "object": {
            "const": "estimate"
          },
          "mode": {
            "type": "string",
            "enum": [
              "live",
              "test"
            ]
          },
          "records": {
            "type": "integer"
          },
          "free_sample_records": {
            "type": "integer"
          },
          "full_audit_cost_credits": {
            "type": "integer"
          },
          "balance_credits": {
            "type": "integer"
          },
          "sufficient_credits": {
            "type": "boolean"
          },
          "credits_needed": {
            "type": "integer"
          },
          "already_processed_audit_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "economics_version": {
            "type": "string"
          },
          "top_up_url": {
            "type": "string"
          }
        }
      },
      "Classifications": {
        "type": "object",
        "properties": {
          "process": {
            "type": "integer"
          },
          "review": {
            "type": "integer"
          },
          "verify": {
            "type": "integer"
          },
          "discard": {
            "type": "integer"
          }
        }
      },
      "Audit": {
        "type": "object",
        "properties": {
          "object": {
            "const": "audit"
          },
          "id": {
            "type": "string"
          },
          "mode": {
            "type": "string",
            "enum": [
              "sample",
              "full"
            ]
          },
          "file_name": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "total_records": {
            "type": "integer"
          },
          "audited_records": {
            "type": "integer"
          },
          "ruleset_version": {
            "type": "string"
          },
          "readiness_pct": {
            "type": "number"
          },
          "classifications": {
            "$ref": "#/components/schemas/Classifications"
          },
          "summary": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            }
          },
          "issues": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "label": {
                  "type": "string"
                },
                "count": {
                  "type": "integer"
                },
                "percent": {
                  "type": "string"
                }
              }
            }
          },
          "destination": {},
          "rows": {
            "type": "array",
            "description": "Up to 1,000 rows; every row is in the annotated CSV.",
            "items": {
              "type": "object",
              "properties": {
                "row": {
                  "type": "integer"
                },
                "name": {
                  "type": "string"
                },
                "company": {
                  "type": "string"
                },
                "email": {
                  "type": "string"
                },
                "domain": {
                  "type": "string"
                },
                "decision": {
                  "type": "string",
                  "enum": [
                    "process",
                    "review",
                    "verify",
                    "discard"
                  ]
                },
                "score": {
                  "type": "number"
                },
                "reason_codes": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "reasons": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "rows_returned": {
            "type": "integer"
          },
          "rows_truncated": {
            "type": "boolean"
          },
          "annotated_csv_url": {
            "type": "string"
          },
          "annotated_csv_expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "billing": {
            "type": "object",
            "properties": {
              "credits_charged": {
                "type": "integer"
              },
              "balance_after": {
                "type": "integer"
              },
              "rerun": {
                "type": "boolean"
              }
            }
          },
          "idempotent_replay": {
            "type": "boolean"
          }
        }
      },
      "StoredAudit": {
        "type": "object",
        "properties": {
          "object": {
            "const": "audit"
          },
          "id": {
            "type": "string"
          },
          "mode": {
            "type": "string",
            "enum": [
              "sample",
              "full"
            ]
          },
          "file_name": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "total_records": {
            "type": "integer"
          },
          "audited_records": {
            "type": "integer"
          },
          "ruleset_version": {
            "type": "string"
          },
          "classifications": {
            "$ref": "#/components/schemas/Classifications"
          },
          "finding_counts": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            }
          },
          "destination": {},
          "annotated_csv_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "annotated_csv_expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "expired": {
            "type": "boolean"
          },
          "billing": {
            "type": "object",
            "properties": {
              "credits_charged": {
                "type": "integer"
              }
            }
          },
          "idempotent_replay": {
            "type": "boolean"
          }
        }
      }
    }
  }
}
