{
  "openapi": "3.1.0",
  "info": {
    "title": "Lempile People API",
    "version": "1.0.0",
    "description": "Gated People Database V1 search and reveal flows. Search returns lead metadata, facets, and contact availability/status only. Raw email and phone values are returned only by the separate reveal endpoint when the source, workspace, credits, and API scope are approved."
  },
  "servers": [
    {
      "url": "https://api.lempile.com",
      "description": "Lempile production API"
    }
  ],
  "tags": [
    {
      "name": "People Search",
      "description": "Search approved people snapshots with safe contact availability metadata."
    },
    {
      "name": "People Reveal",
      "description": "Reveal raw contact details through a separate compliance, credit, and audit gate."
    }
  ],
  "paths": {
    "/people/search": {
      "post": {
        "operationId": "PeopleSearch_search",
        "summary": "Search people",
        "tags": ["People Search"],
        "description": "Searches active, provenance-approved people snapshots. Platform admins may set `sample: true` to search synthetic admin sample records. This route requires `people.read`.",
        "security": [{ "ApiKeyAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/PeopleSearchRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "People search result.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/PeopleSearchResult" }
              }
            }
          },
          "400": {
            "description": "Invalid request body, filters, facets, or pagination.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          },
          "403": {
            "description": "API key lacks `people.read`, or sample mode was requested by a non-admin key.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          }
        }
      }
    },
    "/people/reveal": {
      "post": {
        "operationId": "PeopleReveal_reveal",
        "summary": "Reveal people contact details",
        "tags": ["People Reveal"],
        "description": "Reveals raw contact details for an approved people record. This route requires `people.reveal`, reveal-approved source provenance, workspace credits, rate-limit clearance, and writes an audit event. Repeated reveals of the same contact by the same workspace are not charged again.",
        "security": [{ "ApiKeyAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/PeopleRevealRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "People contact reveal result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PeopleContactRevealResult"
                }
              }
            }
          },
          "400": {
            "description": "Invalid reveal request.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          },
          "402": {
            "description": "Workspace has no People reveal credits available.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          },
          "403": {
            "description": "API key lacks `people.reveal`, or the source is not approved for reveal.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          },
          "404": {
            "description": "Contact record or requested contact field is not available.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          },
          "429": {
            "description": "People reveal rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-KEY"
      }
    },
    "schemas": {
      "PeopleSearchRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "person_countries": {
            "type": "array",
            "items": { "type": "string" }
          },
          "person_locations": {
            "type": "array",
            "items": { "type": "string" }
          },
          "job_titles": {
            "type": "array",
            "items": { "type": "string" }
          },
          "seniorities": {
            "type": "array",
            "items": { "type": "string" }
          },
          "company_domains": {
            "type": "array",
            "items": { "type": "string" }
          },
          "company_employee_ranges": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/EmployeeRange" }
          },
          "company_industries": {
            "type": "array",
            "items": { "type": "string" }
          },
          "email_statuses": {
            "type": "array",
            "items": { "type": "string" }
          },
          "has_email": { "type": "boolean" },
          "facets": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "person_country",
                "seniority",
                "company_size",
                "company_industry",
                "email_status",
                "has_email"
              ]
            }
          },
          "page": {
            "type": "integer",
            "minimum": 1,
            "maximum": 500,
            "default": 1
          },
          "per_page": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100,
            "default": 25
          },
          "sample": {
            "type": "boolean",
            "description": "Platform-admin-only synthetic sample mode."
          }
        }
      },
      "EmployeeRange": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "min": { "type": "integer", "minimum": 0 },
          "max": { "type": "integer", "minimum": 0 }
        }
      },
      "PeopleSearchResult": {
        "type": "object",
        "properties": {
          "object": { "const": "people_search_result" },
          "total": { "type": "integer" },
          "page": { "type": "integer" },
          "per_page": { "type": "integer" },
          "has_more": { "type": "boolean" },
          "data": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/PeopleSearchRecord" }
          },
          "facets": {
            "type": "object",
            "additionalProperties": {
              "type": "object",
              "additionalProperties": { "type": "integer" }
            }
          }
        },
        "required": [
          "object",
          "total",
          "page",
          "per_page",
          "has_more",
          "data",
          "facets"
        ]
      },
      "PeopleRevealRequest": {
        "type": "object",
        "additionalProperties": false,
        "anyOf": [
          { "required": ["record_id"] },
          { "required": ["source_record_id"] }
        ],
        "properties": {
          "record_id": {
            "type": "string",
            "description": "Search result record id returned by `/people/search`."
          },
          "source_record_id": {
            "type": "string",
            "description": "Stable source record id returned in the search result source object."
          },
          "fields": {
            "type": "array",
            "default": ["email", "phone"],
            "items": {
              "type": "string",
              "enum": ["email", "phone"]
            }
          }
        }
      },
      "PeopleContactRevealResult": {
        "type": "object",
        "properties": {
          "object": { "const": "people_contact" },
          "record_id": { "type": ["string", "null"] },
          "source_record_id": { "type": "string" },
          "charged": { "type": "boolean" },
          "remaining_credits": { "type": ["integer", "null"] },
          "contact": {
            "type": "object",
            "properties": {
              "email": { "type": ["string", "null"] },
              "email_status": { "type": ["string", "null"] },
              "email_confidence": { "type": ["number", "null"] },
              "phone": { "type": ["string", "null"] },
              "phone_status": { "type": ["string", "null"] }
            },
            "required": [
              "email",
              "email_status",
              "email_confidence",
              "phone",
              "phone_status"
            ]
          }
        },
        "required": [
          "object",
          "record_id",
          "source_record_id",
          "charged",
          "remaining_credits",
          "contact"
        ]
      },
      "PeopleSearchRecord": {
        "type": "object",
        "properties": {
          "object": { "const": "person_search_record" },
          "id": { "type": "string" },
          "person_name": { "type": "string" },
          "first_name": { "type": ["string", "null"] },
          "last_name": { "type": ["string", "null"] },
          "title": { "type": ["string", "null"] },
          "title_normalized": { "type": ["string", "null"] },
          "function_primary": { "type": ["string", "null"] },
          "seniority": { "type": ["string", "null"] },
          "linkedin_url": { "type": ["string", "null"] },
          "location": { "type": "object" },
          "company": { "type": "object" },
          "contact": {
            "type": "object",
            "properties": {
              "email_available": { "type": "boolean" },
              "email_status": { "type": ["string", "null"] },
              "email_confidence": { "type": ["number", "null"] },
              "phone_available": { "type": "boolean" },
              "phone_status": { "type": ["string", "null"] }
            }
          },
          "source": { "type": "object" }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": { "type": "string" },
          "message": { "type": "string" }
        },
        "required": ["error", "message"]
      }
    }
  }
}
