{
  "openapi": "3.1.0",
  "info": {
    "title": "orbitreach API",
    "version": "1.0.0",
    "summary": "Workspace-scoped REST API for orbitreach.",
    "description": "The public orbitreach API is scoped to the workspace that owns the API key. Workspace admins create and revoke keys in Settings → API. Authenticate with `Authorization: Bearer orb_...` (recommended) or an `X-API-Key` header. The API never accepts browser sessions as authentication. An MCP server using the same keys is available at https://orbitreach.io/api/mcp — see https://orbitreach.io/docs/mcp.md.",
    "contact": {
      "name": "orbitreach support",
      "email": "support@orbitreach.io"
    },
    "termsOfService": "https://orbitreach.io/terms"
  },
  "externalDocs": {
    "description": "orbitreach developer portal",
    "url": "https://orbitreach.io/developers"
  },
  "servers": [
    {
      "url": "https://orbitreach.io",
      "description": "Production"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    },
    {
      "apiKeyHeader": []
    }
  ],
  "tags": [
    {
      "name": "Lead tables",
      "description": "Create and configure lead tables."
    },
    {
      "name": "Leads",
      "description": "Read and import workspace leads."
    },
    {
      "name": "Local leads",
      "description": "Natural-language local business discovery backed by Google Places and public website research."
    },
    {
      "name": "Email",
      "description": "Email verification and business email finding."
    }
  ],
  "paths": {
    "/api/v1/tables": {
      "get": {
        "tags": [
          "Lead tables"
        ],
        "operationId": "listLeadTables",
        "summary": "List active lead tables",
        "responses": {
          "200": {
            "description": "The workspace's active lead tables.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tables": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/LeadTable"
                      }
                    }
                  },
                  "required": [
                    "tables"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "A valid API key is required.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Lead tables"
        ],
        "operationId": "createLeadTable",
        "summary": "Create a lead table",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 80,
                    "description": "Table name."
                  }
                },
                "required": [
                  "name"
                ]
              },
              "example": {
                "name": "Prospects"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The created lead table.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "table": {
                      "$ref": "#/components/schemas/LeadTable"
                    }
                  },
                  "required": [
                    "table"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "A table name is required.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "A valid API key is required.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tables/{id}": {
      "patch": {
        "tags": [
          "Lead tables"
        ],
        "operationId": "updateLeadTableFields",
        "summary": "Update a table's field definitions",
        "description": "Show or hide standard fields and add custom fields. Custom values later use the stable field IDs returned here, for example `custom_owner_email`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            },
            "description": "Lead table id."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "fields": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/LeadFieldDefinition"
                    }
                  }
                },
                "required": [
                  "fields"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated lead table.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "table": {
                      "$ref": "#/components/schemas/LeadTable"
                    }
                  },
                  "required": [
                    "table"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "A valid table id and a fields array are required.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "A valid API key is required.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Lead table not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/leads": {
      "get": {
        "tags": [
          "Leads"
        ],
        "operationId": "listLeads",
        "summary": "List workspace leads",
        "parameters": [
          {
            "name": "tableId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "Limit results to one lead table."
          }
        ],
        "responses": {
          "200": {
            "description": "Workspace leads, most recently updated first.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "leads": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Lead"
                      }
                    }
                  },
                  "required": [
                    "leads"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "A valid API key is required.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Leads"
        ],
        "operationId": "importLeads",
        "summary": "Create or update leads by email",
        "description": "Send one lead object, or `{ \"tableId\": 123, \"leads\": [...] }` with up to 5,000 leads. Creating a lead with an email already in the same table updates that lead.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/LeadInput"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "tableId": {
                        "type": "integer"
                      },
                      "leads": {
                        "type": "array",
                        "minItems": 1,
                        "maxItems": 5000,
                        "items": {
                          "$ref": "#/components/schemas/LeadInput"
                        }
                      }
                    },
                    "required": [
                      "tableId",
                      "leads"
                    ]
                  }
                ]
              },
              "example": {
                "tableId": 123,
                "leads": [
                  {
                    "email": "ada@example.com",
                    "firstName": "Ada",
                    "company": "Example Co"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The number of imported (created or updated) leads.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "imported": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "imported"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid input: a valid tableId and 1–5,000 leads with valid email addresses are required.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "A valid API key is required.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Lead table not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/local-leads": {
      "post": {
        "tags": [
          "Local leads"
        ],
        "operationId": "searchOrImportLocalLeads",
        "summary": "Preview or import local businesses",
        "description": "Send a natural-language prompt such as `10 dentists in Austin rated 4.5+`. Use `mode: \"search\"` to preview without changing a list; omit `mode` to import into an existing `tableId` or a `newTableName`. Google Places returns public business data, not email addresses; unavailable fields remain empty instead of being guessed. Results can include `websiteResearch` and market-specific `registryResearch` with source evidence.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "prompt": {
                    "type": "string",
                    "description": "Natural-language description of the businesses to find."
                  },
                  "mode": {
                    "type": "string",
                    "enum": [
                      "search"
                    ],
                    "description": "Pass `search` to preview without importing."
                  },
                  "tableId": {
                    "type": "integer",
                    "description": "Existing destination lead table (import mode)."
                  },
                  "newTableName": {
                    "type": "string",
                    "description": "Name for a new destination lead table (import mode)."
                  }
                },
                "required": [
                  "prompt"
                ]
              },
              "example": {
                "mode": "search",
                "prompt": "5 restaurants in Lisbon with a rating 4+"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Search preview: interpreted query, constraints, and returned places.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "201": {
            "description": "Import result: returned places, import count, duplicate count, and destination list.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "The prompt could not be interpreted, or the input was invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "A valid API key is required.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "This workspace has used all credits for the current month.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/email/verify": {
      "post": {
        "tags": [
          "Email"
        ],
        "operationId": "verifyEmails",
        "summary": "Verify email addresses",
        "description": "Verify a single `email` or an `emails` array.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "emails": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "email"
                    }
                  }
                }
              },
              "example": {
                "email": "ada@example.com"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Verification results per address.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Provide an email address, or an emails array.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "A valid API key is required.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "This workspace has used all credits for the current month.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Email verification failed upstream.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Email verification is not configured on this server.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/email/find": {
      "post": {
        "tags": [
          "Email"
        ],
        "operationId": "findEmails",
        "summary": "Find a person's business email",
        "description": "Provide `personName` plus `website` or `domain` (or a `people` array of such objects). Results include the method, confidence, MX status, and evidence; addresses are never guessed without evidence.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "personName": {
                    "type": "string"
                  },
                  "website": {
                    "type": "string"
                  },
                  "domain": {
                    "type": "string"
                  },
                  "knownCompanyEmail": {
                    "type": "string",
                    "format": "email"
                  },
                  "people": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "personName": {
                          "type": "string"
                        },
                        "website": {
                          "type": "string"
                        },
                        "domain": {
                          "type": "string"
                        },
                        "knownCompanyEmail": {
                          "type": "string",
                          "format": "email"
                        }
                      },
                      "required": [
                        "personName"
                      ]
                    }
                  }
                }
              },
              "example": {
                "personName": "Ada Lovelace",
                "domain": "example.com"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Find results per person.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Provide personName plus website or domain, or a people array.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "A valid API key is required.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "This workspace has used all credits for the current month.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Email finding is not configured on this server.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "orb_ API key",
        "description": "Workspace API key created in Settings → API, sent as `Authorization: Bearer orb_...`."
      },
      "apiKeyHeader": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "Workspace API key sent as an `X-API-Key` header."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          }
        },
        "required": [
          "error"
        ]
      },
      "LeadStatus": {
        "type": "string",
        "enum": [
          "new",
          "ready",
          "contacted",
          "bounced",
          "replied",
          "interested",
          "not_interested",
          "meeting_booked"
        ]
      },
      "LeadFieldDefinition": {
        "type": "object",
        "description": "A standard or custom lead field. Custom field IDs are stable and prefixed with `custom_`.",
        "properties": {
          "id": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "hidden": {
            "type": "boolean"
          }
        }
      },
      "LeadTable": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "leadCount": {
            "type": "integer"
          },
          "fields": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LeadFieldDefinition"
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name"
        ]
      },
      "LeadInput": {
        "type": "object",
        "properties": {
          "tableId": {
            "type": "integer"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "firstName": {
            "type": "string"
          },
          "lastName": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "company": {
            "type": "string"
          },
          "role": {
            "type": "string"
          },
          "website": {
            "type": "string"
          },
          "linkedin": {
            "type": "string"
          },
          "phone": {
            "type": "string"
          },
          "address": {
            "type": "string"
          },
          "rating": {
            "type": "number"
          },
          "customFields": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Keyed by stable custom field IDs from the tables endpoint."
          },
          "status": {
            "$ref": "#/components/schemas/LeadStatus"
          }
        },
        "required": [
          "email"
        ]
      },
      "Lead": {
        "allOf": [
          {
            "$ref": "#/components/schemas/LeadInput"
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "mapsUrl": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "source": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "sourceId": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "createdAt": {
                "type": "string",
                "format": "date-time"
              },
              "updatedAt": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        ]
      }
    }
  }
}