{
  "openapi": "3.0.3",
  "info": {
    "title": "VertexCRM API",
    "version": "1.0.0",
    "description": "Org-scoped REST API for accounts, contacts, leads, opportunities, and cases. Authenticate with a session cookie, a login JWT, or an organization API key (prefix vcr_). Human guide: /developers and docs/developers/PUBLIC-API.md. Live spec: GET /docs/openapi.json.",
    "contact": {
      "name": "VertexCRM",
      "url": "https://www.vertexcrm.in/contact"
    }
  },
  "servers": [
    { "url": "https://www.vertexcrm.in/api/v1", "description": "Production" },
    { "url": "/api/v1", "description": "This host" }
  ],
  "tags": [
    { "name": "Accounts" },
    { "name": "Contacts" },
    { "name": "Leads" },
    { "name": "Opportunities" },
    { "name": "Cases" }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "JWT from login, or API key starting with vcr_"
      }
    },
    "parameters": {
      "org": {
        "name": "org",
        "in": "query",
        "schema": { "type": "string" },
        "description": "Organization slug. Required for session/JWT users in more than one org. API keys are already org-scoped."
      },
      "page": {
        "name": "page",
        "in": "query",
        "schema": { "type": "integer", "minimum": 1, "default": 1 }
      },
      "sort": {
        "name": "sort",
        "in": "query",
        "schema": { "type": "string" }
      },
      "dir": {
        "name": "dir",
        "in": "query",
        "schema": { "type": "string", "enum": ["asc", "desc"] }
      },
      "id": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": { "type": "integer", "format": "int64" }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": { "error": { "type": "string" } }
      },
      "OK": {
        "type": "object",
        "properties": { "ok": { "type": "boolean" } }
      },
      "Account": {
        "type": "object",
        "properties": {
          "id": { "type": "integer", "format": "int64", "readOnly": true },
          "organization_id": { "type": "integer", "format": "int64", "readOnly": true },
          "name": { "type": "string" },
          "website": { "type": "string" },
          "phone": { "type": "string" },
          "industry": { "type": "string" },
          "annual_revenue": { "type": "string" },
          "employees": { "type": "string" },
          "address": { "type": "string" },
          "city": { "type": "string" },
          "state": { "type": "string" },
          "postal_code": { "type": "string" },
          "country": { "type": "string" },
          "description": { "type": "string" },
          "owner_id": { "type": "integer", "format": "int64", "nullable": true, "readOnly": true },
          "created_by_id": { "type": "integer", "format": "int64", "nullable": true, "readOnly": true },
          "last_modified_by_id": { "type": "integer", "format": "int64", "nullable": true, "readOnly": true },
          "created_at": { "type": "string", "format": "date-time", "readOnly": true },
          "updated_at": { "type": "string", "format": "date-time", "readOnly": true }
        }
      },
      "Contact": {
        "type": "object",
        "properties": {
          "id": { "type": "integer", "format": "int64", "readOnly": true },
          "organization_id": { "type": "integer", "format": "int64", "readOnly": true },
          "account_id": { "type": "integer", "format": "int64", "nullable": true },
          "first_name": { "type": "string" },
          "last_name": { "type": "string" },
          "email": { "type": "string" },
          "phone": { "type": "string" },
          "title": { "type": "string" },
          "department": { "type": "string" },
          "timezone": { "type": "string", "example": "Asia/Kolkata" },
          "linkedin_url": { "type": "string" },
          "instagram_handle": { "type": "string" },
          "facebook_url": { "type": "string" },
          "description": { "type": "string" },
          "owner_id": { "type": "integer", "format": "int64", "nullable": true, "readOnly": true },
          "created_by_id": { "type": "integer", "format": "int64", "nullable": true, "readOnly": true },
          "last_modified_by_id": { "type": "integer", "format": "int64", "nullable": true, "readOnly": true },
          "created_at": { "type": "string", "format": "date-time", "readOnly": true },
          "updated_at": { "type": "string", "format": "date-time", "readOnly": true }
        }
      },
      "Lead": {
        "type": "object",
        "properties": {
          "id": { "type": "integer", "format": "int64", "readOnly": true },
          "organization_id": { "type": "integer", "format": "int64", "readOnly": true },
          "first_name": { "type": "string" },
          "last_name": { "type": "string" },
          "company": { "type": "string" },
          "email": { "type": "string" },
          "phone": { "type": "string" },
          "status": {
            "type": "string",
            "enum": ["Open - Not Contacted", "Working - Contacted", "Closed - Converted", "Closed - Not Converted"]
          },
          "rating": { "type": "string", "enum": ["Hot", "Warm", "Cold"] },
          "source": { "type": "string" },
          "lead_score": { "type": "integer" },
          "timezone": { "type": "string" },
          "linkedin_url": { "type": "string" },
          "instagram_handle": { "type": "string" },
          "facebook_url": { "type": "string" },
          "description": { "type": "string" },
          "meta_ad_id": { "type": "string" },
          "meta_form_id": { "type": "string" },
          "meta_campaign_id": { "type": "string" },
          "meta_leadgen_id": { "type": "string" },
          "owner_id": { "type": "integer", "format": "int64", "nullable": true, "readOnly": true },
          "created_by_id": { "type": "integer", "format": "int64", "nullable": true, "readOnly": true },
          "last_modified_by_id": { "type": "integer", "format": "int64", "nullable": true, "readOnly": true },
          "created_at": { "type": "string", "format": "date-time", "readOnly": true },
          "updated_at": { "type": "string", "format": "date-time", "readOnly": true }
        }
      },
      "Opportunity": {
        "type": "object",
        "properties": {
          "id": { "type": "integer", "format": "int64", "readOnly": true },
          "organization_id": { "type": "integer", "format": "int64", "readOnly": true },
          "account_id": { "type": "integer", "format": "int64", "nullable": true },
          "name": { "type": "string" },
          "amount": { "type": "number" },
          "stage": {
            "type": "string",
            "enum": ["Prospecting", "Qualification", "Needs Analysis", "Value Proposition", "Negotiation", "Closed Won", "Closed Lost"]
          },
          "close_date": { "type": "string", "format": "date-time", "nullable": true },
          "probability": { "type": "integer" },
          "description": { "type": "string" },
          "owner_id": { "type": "integer", "format": "int64", "nullable": true, "readOnly": true },
          "created_by_id": { "type": "integer", "format": "int64", "nullable": true, "readOnly": true },
          "last_modified_by_id": { "type": "integer", "format": "int64", "nullable": true, "readOnly": true },
          "created_at": { "type": "string", "format": "date-time", "readOnly": true },
          "updated_at": { "type": "string", "format": "date-time", "readOnly": true }
        }
      },
      "Case": {
        "type": "object",
        "properties": {
          "id": { "type": "integer", "format": "int64", "readOnly": true },
          "organization_id": { "type": "integer", "format": "int64", "readOnly": true },
          "subject": { "type": "string" },
          "status": { "type": "string", "enum": ["New", "Working", "Escalated", "Closed", "On Hold"] },
          "priority": { "type": "string", "enum": ["High", "Medium", "Low"] },
          "account_id": { "type": "integer", "format": "int64", "nullable": true },
          "contact_id": { "type": "integer", "format": "int64", "nullable": true },
          "owner_id": { "type": "integer", "format": "int64", "nullable": true, "readOnly": true },
          "queue_id": { "type": "integer", "format": "int64", "nullable": true },
          "description": { "type": "string" },
          "sla_due_date": { "type": "string", "format": "date-time", "nullable": true, "readOnly": true },
          "created_at": { "type": "string", "format": "date-time", "readOnly": true },
          "updated_at": { "type": "string", "format": "date-time", "readOnly": true },
          "account_name": { "type": "string", "readOnly": true },
          "contact_name": { "type": "string", "readOnly": true }
        }
      },
      "AccountList": {
        "type": "object",
        "properties": {
          "data": { "type": "array", "items": { "$ref": "#/components/schemas/Account" } },
          "page": { "type": "integer" },
          "per_page": { "type": "integer", "description": "Always 20" }
        }
      },
      "ContactList": {
        "type": "object",
        "properties": {
          "data": { "type": "array", "items": { "$ref": "#/components/schemas/Contact" } },
          "page": { "type": "integer" },
          "per_page": { "type": "integer" }
        }
      },
      "LeadList": {
        "type": "object",
        "properties": {
          "data": { "type": "array", "items": { "$ref": "#/components/schemas/Lead" } },
          "page": { "type": "integer" },
          "per_page": { "type": "integer" }
        }
      },
      "OpportunityList": {
        "type": "object",
        "properties": {
          "data": { "type": "array", "items": { "$ref": "#/components/schemas/Opportunity" } },
          "page": { "type": "integer" },
          "per_page": { "type": "integer" }
        }
      },
      "CaseList": {
        "type": "object",
        "properties": {
          "data": { "type": "array", "items": { "$ref": "#/components/schemas/Case" } },
          "page": { "type": "integer" },
          "per_page": { "type": "integer" }
        }
      }
    }
  },
  "security": [{ "bearerAuth": [] }],
  "paths": {
    "/accounts": {
      "get": {
        "tags": ["Accounts"],
        "summary": "List accounts",
        "parameters": [
          { "$ref": "#/components/parameters/org" },
          { "$ref": "#/components/parameters/page" },
          { "$ref": "#/components/parameters/sort" },
          { "$ref": "#/components/parameters/dir" }
        ],
        "responses": {
          "200": { "description": "OK", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountList" } } } }
        }
      },
      "post": {
        "tags": ["Accounts"],
        "summary": "Create account",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Account" } } } },
        "responses": {
          "201": { "description": "Created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Account" } } } }
        }
      }
    },
    "/accounts/{id}": {
      "get": {
        "tags": ["Accounts"],
        "summary": "Get account",
        "parameters": [{ "$ref": "#/components/parameters/id" }],
        "responses": {
          "200": { "description": "OK", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Account" } } } },
          "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      },
      "put": {
        "tags": ["Accounts"],
        "summary": "Update account",
        "parameters": [{ "$ref": "#/components/parameters/id" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Account" } } } },
        "responses": {
          "200": { "description": "OK", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Account" } } } }
        }
      },
      "delete": {
        "tags": ["Accounts"],
        "summary": "Delete account",
        "parameters": [{ "$ref": "#/components/parameters/id" }],
        "responses": {
          "200": { "description": "Deleted", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OK" } } } }
        }
      }
    },
    "/contacts": {
      "get": {
        "tags": ["Contacts"],
        "summary": "List contacts",
        "parameters": [
          { "$ref": "#/components/parameters/org" },
          { "$ref": "#/components/parameters/page" },
          { "$ref": "#/components/parameters/sort" },
          { "$ref": "#/components/parameters/dir" }
        ],
        "responses": {
          "200": { "description": "OK", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ContactList" } } } }
        }
      },
      "post": {
        "tags": ["Contacts"],
        "summary": "Create contact",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Contact" } } } },
        "responses": {
          "201": { "description": "Created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Contact" } } } }
        }
      }
    },
    "/contacts/{id}": {
      "get": {
        "tags": ["Contacts"],
        "summary": "Get contact",
        "parameters": [{ "$ref": "#/components/parameters/id" }],
        "responses": {
          "200": { "description": "OK", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Contact" } } } },
          "404": { "description": "Not found" }
        }
      },
      "put": {
        "tags": ["Contacts"],
        "summary": "Update contact",
        "parameters": [{ "$ref": "#/components/parameters/id" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Contact" } } } },
        "responses": { "200": { "description": "OK" } }
      },
      "delete": {
        "tags": ["Contacts"],
        "summary": "Delete contact",
        "parameters": [{ "$ref": "#/components/parameters/id" }],
        "responses": { "200": { "description": "Deleted" } }
      }
    },
    "/leads": {
      "get": {
        "tags": ["Leads"],
        "summary": "List leads",
        "parameters": [
          { "$ref": "#/components/parameters/org" },
          { "$ref": "#/components/parameters/page" },
          { "$ref": "#/components/parameters/sort" },
          { "$ref": "#/components/parameters/dir" },
          { "name": "status", "in": "query", "schema": { "type": "string" } },
          { "name": "rating", "in": "query", "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "OK", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LeadList" } } } }
        }
      },
      "post": {
        "tags": ["Leads"],
        "summary": "Create lead",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Lead" } } } },
        "responses": {
          "201": { "description": "Created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Lead" } } } }
        }
      }
    },
    "/leads/{id}": {
      "get": {
        "tags": ["Leads"],
        "summary": "Get lead",
        "parameters": [{ "$ref": "#/components/parameters/id" }],
        "responses": {
          "200": { "description": "OK", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Lead" } } } },
          "404": { "description": "Not found" }
        }
      },
      "put": {
        "tags": ["Leads"],
        "summary": "Update lead",
        "parameters": [{ "$ref": "#/components/parameters/id" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Lead" } } } },
        "responses": { "200": { "description": "OK" } }
      },
      "delete": {
        "tags": ["Leads"],
        "summary": "Delete lead",
        "parameters": [{ "$ref": "#/components/parameters/id" }],
        "responses": { "200": { "description": "Deleted" } }
      }
    },
    "/opportunities": {
      "get": {
        "tags": ["Opportunities"],
        "summary": "List opportunities",
        "parameters": [
          { "$ref": "#/components/parameters/org" },
          { "$ref": "#/components/parameters/page" },
          { "$ref": "#/components/parameters/sort" },
          { "$ref": "#/components/parameters/dir" },
          { "name": "stage", "in": "query", "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "OK", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OpportunityList" } } } }
        }
      },
      "post": {
        "tags": ["Opportunities"],
        "summary": "Create opportunity",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Opportunity" } } } },
        "responses": {
          "201": { "description": "Created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Opportunity" } } } }
        }
      }
    },
    "/opportunities/{id}": {
      "get": {
        "tags": ["Opportunities"],
        "summary": "Get opportunity",
        "parameters": [{ "$ref": "#/components/parameters/id" }],
        "responses": {
          "200": { "description": "OK", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Opportunity" } } } },
          "404": { "description": "Not found" }
        }
      },
      "put": {
        "tags": ["Opportunities"],
        "summary": "Update opportunity",
        "parameters": [{ "$ref": "#/components/parameters/id" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Opportunity" } } } },
        "responses": { "200": { "description": "OK" } }
      },
      "delete": {
        "tags": ["Opportunities"],
        "summary": "Delete opportunity",
        "parameters": [{ "$ref": "#/components/parameters/id" }],
        "responses": { "200": { "description": "Deleted" } }
      }
    },
    "/cases": {
      "get": {
        "tags": ["Cases"],
        "summary": "List cases",
        "parameters": [
          { "$ref": "#/components/parameters/org" },
          { "$ref": "#/components/parameters/page" },
          { "name": "status", "in": "query", "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "OK", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CaseList" } } } }
        }
      },
      "post": {
        "tags": ["Cases"],
        "summary": "Create case",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Case" } } } },
        "responses": {
          "201": { "description": "Created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Case" } } } }
        }
      }
    },
    "/cases/{id}": {
      "get": {
        "tags": ["Cases"],
        "summary": "Get case",
        "parameters": [{ "$ref": "#/components/parameters/id" }],
        "responses": {
          "200": { "description": "OK", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Case" } } } },
          "404": { "description": "Not found" }
        }
      },
      "put": {
        "tags": ["Cases"],
        "summary": "Update case",
        "parameters": [{ "$ref": "#/components/parameters/id" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Case" } } } },
        "responses": { "200": { "description": "OK" } }
      },
      "delete": {
        "tags": ["Cases"],
        "summary": "Delete case",
        "parameters": [{ "$ref": "#/components/parameters/id" }],
        "responses": { "200": { "description": "Deleted" } }
      }
    }
  }
}
