{
  "openapi": "3.1.0",
  "info": {
    "title": "Relm CRM API",
    "version": "0.14.0",
    "summary": "API-first CRM built for LLMs and AI agents.",
    "description": "REST surface for Relm. Every operation is also available as a typed MCP tool at https://api.relmcrm.com/mcp and over A2A at https://api.relmcrm.com/a2a. Auth is a workspace-scoped bearer key (relm_live_ / relm_test_). Errors are RFC-9457 problem+json with valid_options and a suggestion so an agent self-corrects. Read GET /schema first to learn the live objects, fields and enum values.",
    "contact": { "name": "Relm", "url": "https://relmcrm.com/" },
    "license": { "name": "Proprietary" }
  },
  "servers": [{ "url": "https://api.relmcrm.com/v1", "description": "Production" }],
  "security": [{ "bearerAuth": [] }],
  "tags": [
    { "name": "Discovery", "description": "Self-describing schema, usage, settings." },
    { "name": "Contacts" }, { "name": "Companies" }, { "name": "Deals" }, { "name": "Activities" },
    { "name": "Pipelines" }, { "name": "Search" }, { "name": "Registry", "description": "Custom fields, enums, object types." },
    { "name": "Automations" }, { "name": "Sequences" }, { "name": "Templates" }, { "name": "Connections" },
    { "name": "Webhooks" }, { "name": "Batch" }
  ],
  "paths": {
    "/schema": { "get": { "tags": ["Discovery"], "operationId": "getSchema", "summary": "Live object/field/enum registry.", "description": "Returns every object with its fields, id_prefix and list_filters, all enum groups, list_controls, the automation capability catalog, and usage notes. Call this before guessing a type, field or filter.", "responses": { "200": { "description": "Schema document", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SchemaDoc" } } } }, "default": { "$ref": "#/components/responses/Problem" } } } },
    "/usage": { "get": { "tags": ["Discovery"], "operationId": "getUsage", "summary": "Current billing period usage.", "responses": { "200": { "description": "Usage", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Usage" } } } }, "default": { "$ref": "#/components/responses/Problem" } } } },
    "/settings": {
      "get": { "tags": ["Discovery"], "operationId": "getSettings", "summary": "Workspace settings (spend cap).", "responses": { "200": { "description": "Settings", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Settings" } } } }, "default": { "$ref": "#/components/responses/Problem" } } },
      "patch": { "tags": ["Discovery"], "operationId": "setSettings", "summary": "Set the monthly overage spend cap.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["overage_cap_usd"], "properties": { "overage_cap_usd": { "type": ["number", "null"], "description": "USD cap on metered overage; 0 = never any overage, null = unlimited." } } } } } }, "responses": { "200": { "description": "Settings", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Settings" } } } }, "default": { "$ref": "#/components/responses/Problem" } } }
    },
    "/search": { "get": { "tags": ["Search"], "operationId": "search", "summary": "Cross-object search over contacts, companies and deals.", "parameters": [ { "name": "q", "in": "query", "required": true, "schema": { "type": "string" }, "description": "Substring to match." }, { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 10, "maximum": 100 } } ], "responses": { "200": { "description": "Search results (has_more=true if any section was truncated).", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SearchResult" } } } }, "default": { "$ref": "#/components/responses/Problem" } } } },
    "/enums": {
      "get": { "tags": ["Registry"], "operationId": "listEnums", "summary": "All enum groups and their values.", "responses": { "200": { "description": "Enum groups", "content": { "application/json": { "schema": { "type": "object" } } } }, "default": { "$ref": "#/components/responses/Problem" } } },
      "post": { "tags": ["Registry"], "operationId": "createEnumValue", "summary": "Add a value to an enum group (idempotent).", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["group", "value"], "properties": { "group": { "type": "string", "example": "contact.type" }, "value": { "type": "string" }, "label": { "type": "string" } } } } } }, "responses": { "201": { "description": "Updated value set", "content": { "application/json": { "schema": { "type": "object" } } } }, "default": { "$ref": "#/components/responses/Problem" } } }
    },
    "/fields": { "post": { "tags": ["Registry"], "operationId": "createField", "summary": "Register a custom field on an object.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["object", "key"], "properties": { "object": { "type": "string", "enum": ["contact", "company", "deal", "activity"] }, "key": { "type": "string" }, "label": { "type": "string" }, "data_type": { "type": "string", "enum": ["text", "number", "boolean", "date", "select", "multiselect", "currency", "reference", "email", "url"], "default": "text" }, "enum_group": { "type": "string" }, "required": { "type": "boolean" } } } } } }, "responses": { "201": { "description": "Field set", "content": { "application/json": { "schema": { "type": "object" } } } }, "default": { "$ref": "#/components/responses/Problem" } } } },
    "/types": { "post": { "tags": ["Registry"], "operationId": "createType", "summary": "Register a custom object type (schema grouping only).", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["key"], "properties": { "key": { "type": "string" }, "label": { "type": "string" } } } } } }, "responses": { "201": { "description": "Type set", "content": { "application/json": { "schema": { "type": "object" } } } }, "default": { "$ref": "#/components/responses/Problem" } } } },

    "/contacts": {
      "get": { "tags": ["Contacts"], "operationId": "listContacts", "summary": "List contacts.", "parameters": [ { "$ref": "#/components/parameters/Limit" }, { "$ref": "#/components/parameters/Cursor" }, { "$ref": "#/components/parameters/IncludeDeleted" }, { "name": "q", "in": "query", "schema": { "type": "string" }, "description": "Substring over name/email/phone/linkedin." }, { "name": "email", "in": "query", "schema": { "type": "string" } }, { "name": "company_id", "in": "query", "schema": { "type": "string" } }, { "name": "type", "in": "query", "schema": { "type": "string" }, "description": "A registered contact.type value (validated)." } ], "responses": { "200": { "description": "Contact list", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ContactList" } } } }, "default": { "$ref": "#/components/responses/Problem" } } },
      "post": { "tags": ["Contacts"], "operationId": "createContact", "summary": "Create a contact.", "description": "Needs at least one of: a name, an identifier (email/phone/linkedin_url), a company, or a custom field. Email is unique per workspace.", "parameters": [ { "$ref": "#/components/parameters/IdempotencyKey" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ContactInput" } } } }, "responses": { "201": { "description": "Created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Contact" } } } }, "default": { "$ref": "#/components/responses/Problem" } } }
    },
    "/contacts/{id}": {
      "parameters": [ { "$ref": "#/components/parameters/IdPath" } ],
      "get": { "tags": ["Contacts"], "operationId": "getContact", "summary": "Fetch a contact.", "responses": { "200": { "description": "Contact", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Contact" } } } }, "default": { "$ref": "#/components/responses/Problem" } } },
      "patch": { "tags": ["Contacts"], "operationId": "updateContact", "summary": "Update a contact.", "parameters": [ { "$ref": "#/components/parameters/IfMatch" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ContactInput" } } } }, "responses": { "200": { "description": "Updated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Contact" } } } }, "default": { "$ref": "#/components/responses/Problem" } } },
      "delete": { "tags": ["Contacts"], "operationId": "deleteContact", "summary": "Soft-delete a contact.", "responses": { "200": { "description": "Deleted", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Deleted" } } } }, "default": { "$ref": "#/components/responses/Problem" } } }
    },
    "/contacts/{id}/restore": { "parameters": [ { "$ref": "#/components/parameters/IdPath" } ], "post": { "tags": ["Contacts"], "operationId": "restoreContact", "summary": "Restore a soft-deleted contact.", "responses": { "200": { "description": "Restored", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Contact" } } } }, "default": { "$ref": "#/components/responses/Problem" } } } },

    "/companies": {
      "get": { "tags": ["Companies"], "operationId": "listCompanies", "summary": "List companies.", "parameters": [ { "$ref": "#/components/parameters/Limit" }, { "$ref": "#/components/parameters/Cursor" }, { "$ref": "#/components/parameters/IncludeDeleted" }, { "name": "q", "in": "query", "schema": { "type": "string" } }, { "name": "domain", "in": "query", "schema": { "type": "string" } } ], "responses": { "200": { "description": "Company list", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CompanyList" } } } }, "default": { "$ref": "#/components/responses/Problem" } } },
      "post": { "tags": ["Companies"], "operationId": "createCompany", "summary": "Create a company (name required).", "parameters": [ { "$ref": "#/components/parameters/IdempotencyKey" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CompanyInput" } } } }, "responses": { "201": { "description": "Created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Company" } } } }, "default": { "$ref": "#/components/responses/Problem" } } }
    },
    "/companies/{id}": {
      "parameters": [ { "$ref": "#/components/parameters/IdPath" } ],
      "get": { "tags": ["Companies"], "operationId": "getCompany", "summary": "Fetch a company.", "responses": { "200": { "description": "Company", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Company" } } } }, "default": { "$ref": "#/components/responses/Problem" } } },
      "patch": { "tags": ["Companies"], "operationId": "updateCompany", "summary": "Update a company.", "parameters": [ { "$ref": "#/components/parameters/IfMatch" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CompanyInput" } } } }, "responses": { "200": { "description": "Updated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Company" } } } }, "default": { "$ref": "#/components/responses/Problem" } } },
      "delete": { "tags": ["Companies"], "operationId": "deleteCompany", "summary": "Soft-delete a company.", "responses": { "200": { "description": "Deleted", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Deleted" } } } }, "default": { "$ref": "#/components/responses/Problem" } } }
    },
    "/companies/{id}/restore": { "parameters": [ { "$ref": "#/components/parameters/IdPath" } ], "post": { "tags": ["Companies"], "operationId": "restoreCompany", "summary": "Restore a company.", "responses": { "200": { "description": "Restored", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Company" } } } }, "default": { "$ref": "#/components/responses/Problem" } } } },

    "/deals": {
      "get": { "tags": ["Deals"], "operationId": "listDeals", "summary": "List deals.", "parameters": [ { "$ref": "#/components/parameters/Limit" }, { "$ref": "#/components/parameters/Cursor" }, { "$ref": "#/components/parameters/IncludeDeleted" }, { "name": "q", "in": "query", "schema": { "type": "string" } }, { "name": "pipeline", "in": "query", "schema": { "type": "string" }, "description": "Scope to ONE pipeline (key or pl_ id). Omit and you get deals from ALL pipelines merged - pass this whenever you reason about a single funnel, since stage keys are not unique across pipelines. Alias: pipeline_id." }, { "name": "pipeline_id", "in": "query", "schema": { "type": "string" } }, { "name": "stage", "in": "query", "schema": { "type": "string" } }, { "name": "company_id", "in": "query", "schema": { "type": "string" } }, { "name": "primary_contact_id", "in": "query", "schema": { "type": "string" } } ], "responses": { "200": { "description": "Deal list", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DealList" } } } }, "default": { "$ref": "#/components/responses/Problem" } } },
      "post": { "tags": ["Deals"], "operationId": "createDeal", "summary": "Create a deal (title required).", "parameters": [ { "$ref": "#/components/parameters/IdempotencyKey" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DealInput" } } } }, "responses": { "201": { "description": "Created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Deal" } } } }, "default": { "$ref": "#/components/responses/Problem" } } }
    },
    "/deals/{id}": {
      "parameters": [ { "$ref": "#/components/parameters/IdPath" } ],
      "get": { "tags": ["Deals"], "operationId": "getDeal", "summary": "Fetch a deal.", "responses": { "200": { "description": "Deal", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Deal" } } } }, "default": { "$ref": "#/components/responses/Problem" } } },
      "patch": { "tags": ["Deals"], "operationId": "updateDeal", "summary": "Update a deal (incl. moving stage/pipeline).", "parameters": [ { "$ref": "#/components/parameters/IfMatch" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DealInput" } } } }, "responses": { "200": { "description": "Updated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Deal" } } } }, "default": { "$ref": "#/components/responses/Problem" } } },
      "delete": { "tags": ["Deals"], "operationId": "deleteDeal", "summary": "Soft-delete a deal.", "responses": { "200": { "description": "Deleted", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Deleted" } } } }, "default": { "$ref": "#/components/responses/Problem" } } }
    },
    "/deals/{id}/restore": { "parameters": [ { "$ref": "#/components/parameters/IdPath" } ], "post": { "tags": ["Deals"], "operationId": "restoreDeal", "summary": "Restore a deal.", "responses": { "200": { "description": "Restored", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Deal" } } } }, "default": { "$ref": "#/components/responses/Problem" } } } },

    "/activities": {
      "get": { "tags": ["Activities"], "operationId": "listActivities", "summary": "List activities.", "parameters": [ { "$ref": "#/components/parameters/Limit" }, { "$ref": "#/components/parameters/Cursor" }, { "$ref": "#/components/parameters/IncludeDeleted" }, { "name": "contact_id", "in": "query", "schema": { "type": "string" } }, { "name": "deal_id", "in": "query", "schema": { "type": "string" } }, { "name": "type", "in": "query", "schema": { "type": "string" }, "description": "A registered activity.type value (validated)." } ], "responses": { "200": { "description": "Activity list", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ActivityList" } } } }, "default": { "$ref": "#/components/responses/Problem" } } },
      "post": { "tags": ["Activities"], "operationId": "createActivity", "summary": "Log an activity (attach to a contact and/or deal).", "parameters": [ { "$ref": "#/components/parameters/IdempotencyKey" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ActivityInput" } } } }, "responses": { "201": { "description": "Created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Activity" } } } }, "default": { "$ref": "#/components/responses/Problem" } } }
    },
    "/activities/{id}": {
      "parameters": [ { "$ref": "#/components/parameters/IdPath" } ],
      "get": { "tags": ["Activities"], "operationId": "getActivity", "summary": "Fetch an activity.", "responses": { "200": { "description": "Activity", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Activity" } } } }, "default": { "$ref": "#/components/responses/Problem" } } },
      "patch": { "tags": ["Activities"], "operationId": "updateActivity", "summary": "Update an activity.", "parameters": [ { "$ref": "#/components/parameters/IfMatch" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ActivityInput" } } } }, "responses": { "200": { "description": "Updated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Activity" } } } }, "default": { "$ref": "#/components/responses/Problem" } } },
      "delete": { "tags": ["Activities"], "operationId": "deleteActivity", "summary": "Soft-delete an activity.", "responses": { "200": { "description": "Deleted", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Deleted" } } } }, "default": { "$ref": "#/components/responses/Problem" } } }
    },
    "/activities/{id}/restore": { "parameters": [ { "$ref": "#/components/parameters/IdPath" } ], "post": { "tags": ["Activities"], "operationId": "restoreActivity", "summary": "Restore an activity.", "responses": { "200": { "description": "Restored", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Activity" } } } }, "default": { "$ref": "#/components/responses/Problem" } } } },

    "/pipelines": {
      "get": { "tags": ["Pipelines"], "operationId": "listPipelines", "summary": "List pipelines with their ordered stages.", "responses": { "200": { "description": "Pipelines", "content": { "application/json": { "schema": { "type": "object" } } } }, "default": { "$ref": "#/components/responses/Problem" } } },
      "post": { "tags": ["Pipelines"], "operationId": "createPipeline", "summary": "Create a pipeline.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PipelineInput" } } } }, "responses": { "201": { "description": "Created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Pipeline" } } } }, "default": { "$ref": "#/components/responses/Problem" } } }
    },
    "/pipelines/{key}": {
      "parameters": [ { "name": "key", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Pipeline key or pl_ id." } ],
      "get": { "tags": ["Pipelines"], "operationId": "getPipeline", "summary": "Fetch a pipeline.", "responses": { "200": { "description": "Pipeline", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Pipeline" } } } }, "default": { "$ref": "#/components/responses/Problem" } } },
      "patch": { "tags": ["Pipelines"], "operationId": "updatePipeline", "summary": "Update a pipeline: display `name`, `is_default`, and/or re-`key` it. The key is slugified; deals attach by internal id, so a re-key never orphans them. A soft-deleted pipeline's key is reusable.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "properties": { "name": { "type": "string", "description": "New display name" }, "key": { "type": "string", "description": "New pipeline key (slugified); deals follow by internal id." }, "is_default": { "type": "boolean" } } } } } }, "responses": { "200": { "description": "Pipeline", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Pipeline" } } } }, "default": { "$ref": "#/components/responses/Problem" } } },
      "delete": { "tags": ["Pipelines"], "operationId": "deletePipeline", "summary": "Delete a pipeline (fails if deals still use it).", "responses": { "200": { "description": "Deleted", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Deleted" } } } }, "default": { "$ref": "#/components/responses/Problem" } } }
    },
    "/pipelines/{key}/default": { "parameters": [ { "name": "key", "in": "path", "required": true, "schema": { "type": "string" } } ], "post": { "tags": ["Pipelines"], "operationId": "setDefaultPipeline", "summary": "Make this pipeline the workspace default.", "responses": { "200": { "description": "Pipeline", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Pipeline" } } } }, "default": { "$ref": "#/components/responses/Problem" } } } },
    "/pipelines/{key}/stages": { "parameters": [ { "name": "key", "in": "path", "required": true, "schema": { "type": "string" } } ], "post": { "tags": ["Pipelines"], "operationId": "addStage", "summary": "Add a stage to a pipeline.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["key"], "properties": { "key": { "type": "string", "description": "Slugified on write; original kept as label." }, "label": { "type": "string" }, "ordinal": { "type": "integer" }, "type": { "type": "string", "enum": ["open", "won", "lost"] } } } } } }, "responses": { "201": { "description": "Pipeline", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Pipeline" } } } }, "default": { "$ref": "#/components/responses/Problem" } } } },
    "/pipelines/{key}/stages/reorder": { "parameters": [ { "name": "key", "in": "path", "required": true, "schema": { "type": "string" } } ], "post": { "tags": ["Pipelines"], "operationId": "reorderStages", "summary": "Reorder stages (order = a permutation of every existing stage key).", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["order"], "properties": { "order": { "type": "array", "items": { "type": "string" } } } } } } }, "responses": { "200": { "description": "Pipeline", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Pipeline" } } } }, "default": { "$ref": "#/components/responses/Problem" } } } },
    "/pipelines/{key}/stages/{stage}": { "parameters": [ { "name": "key", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "stage", "in": "path", "required": true, "schema": { "type": "string" } } ], "patch": { "tags": ["Pipelines"], "operationId": "updateStage", "summary": "Rename/retype a stage. `key` is slugified; deals on the stage follow automatically (linked by internal id), so this safely fixes a typo'd key or sets the semantic type.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "properties": { "key": { "type": "string", "description": "New key (slugified)." }, "label": { "type": "string" }, "type": { "type": "string", "enum": ["open", "won", "lost"] } } } } } }, "responses": { "200": { "description": "Pipeline", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Pipeline" } } } }, "default": { "$ref": "#/components/responses/Problem" } } }, "delete": { "tags": ["Pipelines"], "operationId": "deleteStage", "summary": "Delete a stage (fails if deals use it).", "responses": { "200": { "description": "Pipeline", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Pipeline" } } } }, "default": { "$ref": "#/components/responses/Problem" } } } },

    "/automations": {
      "get": { "tags": ["Automations"], "operationId": "listAutomations", "summary": "List automations.", "responses": { "200": { "description": "Automations", "content": { "application/json": { "schema": { "type": "object" } } } }, "default": { "$ref": "#/components/responses/Problem" } } },
      "post": { "tags": ["Automations"], "operationId": "createAutomation", "summary": "Create a single-step rule: when <trigger_event> [if <conditions>] then <actions>.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AutomationInput" } } } }, "responses": { "201": { "description": "Created", "content": { "application/json": { "schema": { "type": "object" } } } }, "default": { "$ref": "#/components/responses/Problem" } } }
    },
    "/automations/{id}": {
      "parameters": [ { "$ref": "#/components/parameters/IdPath" } ],
      "get": { "tags": ["Automations"], "operationId": "getAutomation", "summary": "Fetch an automation.", "responses": { "200": { "description": "Automation", "content": { "application/json": { "schema": { "type": "object" } } } }, "default": { "$ref": "#/components/responses/Problem" } } },
      "patch": { "tags": ["Automations"], "operationId": "setAutomationEnabled", "summary": "Enable or disable an automation (only `enabled` is patchable).", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["enabled"], "properties": { "enabled": { "type": "boolean" } } } } } }, "responses": { "200": { "description": "Automation", "content": { "application/json": { "schema": { "type": "object" } } } }, "default": { "$ref": "#/components/responses/Problem" } } },
      "delete": { "tags": ["Automations"], "operationId": "deleteAutomation", "summary": "Delete an automation.", "responses": { "200": { "description": "Deleted", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Deleted" } } } }, "default": { "$ref": "#/components/responses/Problem" } } }
    },
    "/automations-capabilities": { "get": { "tags": ["Automations"], "operationId": "automationsCapabilities", "summary": "Valid trigger events, condition ops, action types and channels.", "responses": { "200": { "description": "Capabilities", "content": { "application/json": { "schema": { "type": "object" } } } }, "default": { "$ref": "#/components/responses/Problem" } } } },

    "/sequences": {
      "get": { "tags": ["Sequences"], "operationId": "listSequences", "summary": "List drip sequences with steps and enrollment counts.", "responses": { "200": { "description": "Sequences", "content": { "application/json": { "schema": { "type": "object" } } } }, "default": { "$ref": "#/components/responses/Problem" } } },
      "post": { "tags": ["Sequences"], "operationId": "createSequence", "summary": "Create a multi-step drip sequence.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SequenceInput" } } } }, "responses": { "201": { "description": "Created", "content": { "application/json": { "schema": { "type": "object" } } } }, "default": { "$ref": "#/components/responses/Problem" } } }
    },
    "/sequences/{id}": {
      "parameters": [ { "$ref": "#/components/parameters/IdPath" } ],
      "get": { "tags": ["Sequences"], "operationId": "getSequence", "summary": "Fetch a sequence.", "responses": { "200": { "description": "Sequence", "content": { "application/json": { "schema": { "type": "object" } } } }, "default": { "$ref": "#/components/responses/Problem" } } },
      "patch": { "tags": ["Sequences"], "operationId": "setSequenceEnabled", "summary": "Enable or disable a sequence (only `enabled` is patchable).", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["enabled"], "properties": { "enabled": { "type": "boolean" } } } } } }, "responses": { "200": { "description": "Sequence", "content": { "application/json": { "schema": { "type": "object" } } } }, "default": { "$ref": "#/components/responses/Problem" } } },
      "delete": { "tags": ["Sequences"], "operationId": "deleteSequence", "summary": "Delete a sequence.", "responses": { "200": { "description": "Deleted", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Deleted" } } } }, "default": { "$ref": "#/components/responses/Problem" } } }
    },
    "/sequences/{id}/preview": { "parameters": [ { "$ref": "#/components/parameters/IdPath" } ], "get": { "tags": ["Sequences"], "operationId": "previewSequence", "summary": "Dry-run: who would enroll now + the send schedule.", "responses": { "200": { "description": "Preview", "content": { "application/json": { "schema": { "type": "object" } } } }, "default": { "$ref": "#/components/responses/Problem" } } } },
    "/sequences/{id}/enrollments": { "parameters": [ { "$ref": "#/components/parameters/IdPath" } ], "get": { "tags": ["Sequences"], "operationId": "listEnrollments", "summary": "List enrollments and their state.", "responses": { "200": { "description": "Enrollments", "content": { "application/json": { "schema": { "type": "object" } } } }, "default": { "$ref": "#/components/responses/Problem" } } } },
    "/sequences/{id}/enroll": { "parameters": [ { "$ref": "#/components/parameters/IdPath" } ], "post": { "tags": ["Sequences"], "operationId": "enroll", "summary": "Manually enroll a contact (idempotent per contact+sequence).", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["contact_id"], "properties": { "contact_id": { "type": "string" }, "source": { "type": "object" } } } } } }, "responses": { "201": { "description": "Enrollment", "content": { "application/json": { "schema": { "type": "object" } } } }, "default": { "$ref": "#/components/responses/Problem" } } } },

    "/templates": {
      "get": { "tags": ["Templates"], "operationId": "listTemplates", "summary": "List email templates.", "responses": { "200": { "description": "Templates", "content": { "application/json": { "schema": { "type": "object" } } } }, "default": { "$ref": "#/components/responses/Problem" } } },
      "post": { "tags": ["Templates"], "operationId": "createTemplate", "summary": "Create a reusable email template.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["name", "html"], "properties": { "name": { "type": "string" }, "key": { "type": "string" }, "subject": { "type": "string" }, "html": { "type": "string" }, "text": { "type": "string" } } } } } }, "responses": { "201": { "description": "Created", "content": { "application/json": { "schema": { "type": "object" } } } }, "default": { "$ref": "#/components/responses/Problem" } } }
    },
    "/templates/{id}": {
      "parameters": [ { "$ref": "#/components/parameters/IdPath" } ],
      "get": { "tags": ["Templates"], "operationId": "getTemplate", "summary": "Fetch a template.", "responses": { "200": { "description": "Template", "content": { "application/json": { "schema": { "type": "object" } } } }, "default": { "$ref": "#/components/responses/Problem" } } },
      "patch": { "tags": ["Templates"], "operationId": "updateTemplate", "summary": "Update a template.", "parameters": [ { "$ref": "#/components/parameters/IfMatch" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object" } } } }, "responses": { "200": { "description": "Template", "content": { "application/json": { "schema": { "type": "object" } } } }, "default": { "$ref": "#/components/responses/Problem" } } },
      "delete": { "tags": ["Templates"], "operationId": "deleteTemplate", "summary": "Delete a template.", "responses": { "200": { "description": "Deleted", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Deleted" } } } }, "default": { "$ref": "#/components/responses/Problem" } } }
    },

    "/connections": {
      "get": { "tags": ["Connections"], "operationId": "listConnections", "summary": "List connected messaging channels (never returns the secret).", "responses": { "200": { "description": "Connections", "content": { "application/json": { "schema": { "type": "object" } } } }, "default": { "$ref": "#/components/responses/Problem" } } },
      "post": { "tags": ["Connections"], "operationId": "createConnection", "summary": "Connect a BYO channel (e.g. email/Resend). Key encrypted at rest.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["api_key"], "properties": { "channel": { "type": "string" }, "provider": { "type": "string" }, "api_key": { "type": "string" }, "from": { "type": "string" }, "name": { "type": "string" } } } } } }, "responses": { "201": { "description": "Created", "content": { "application/json": { "schema": { "type": "object" } } } }, "default": { "$ref": "#/components/responses/Problem" } } }
    },
    "/connections/{id}": { "parameters": [ { "$ref": "#/components/parameters/IdPath" } ], "delete": { "tags": ["Connections"], "operationId": "deleteConnection", "summary": "Delete a connection.", "responses": { "200": { "description": "Deleted", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Deleted" } } } }, "default": { "$ref": "#/components/responses/Problem" } } } },

    "/webhooks": {
      "get": { "tags": ["Webhooks"], "operationId": "listWebhooks", "summary": "List webhook subscriptions.", "responses": { "200": { "description": "Webhooks", "content": { "application/json": { "schema": { "type": "object" } } } }, "default": { "$ref": "#/components/responses/Problem" } } },
      "post": { "tags": ["Webhooks"], "operationId": "createWebhook", "summary": "Subscribe an https endpoint to events. Returns the signing secret once.", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WebhookInput" } } } }, "responses": { "201": { "description": "Created (secret shown once)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Webhook" } } } }, "default": { "$ref": "#/components/responses/Problem" } } }
    },
    "/webhooks/{id}": {
      "parameters": [ { "$ref": "#/components/parameters/IdPath" } ],
      "get": { "tags": ["Webhooks"], "operationId": "getWebhook", "summary": "Fetch a webhook.", "responses": { "200": { "description": "Webhook", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Webhook" } } } }, "default": { "$ref": "#/components/responses/Problem" } } },
      "patch": { "tags": ["Webhooks"], "operationId": "updateWebhook", "summary": "Update a webhook (url/events/description/enabled).", "parameters": [ { "$ref": "#/components/parameters/IfMatch" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WebhookInput" } } } }, "responses": { "200": { "description": "Webhook", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Webhook" } } } }, "default": { "$ref": "#/components/responses/Problem" } } },
      "delete": { "tags": ["Webhooks"], "operationId": "deleteWebhook", "summary": "Delete a webhook.", "responses": { "200": { "description": "Deleted", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Deleted" } } } }, "default": { "$ref": "#/components/responses/Problem" } } }
    },
    "/webhooks/{id}/deliveries": { "parameters": [ { "$ref": "#/components/parameters/IdPath" } ], "get": { "tags": ["Webhooks"], "operationId": "listDeliveries", "summary": "Recent delivery attempts (status, retries, dead-letter).", "responses": { "200": { "description": "Deliveries", "content": { "application/json": { "schema": { "type": "object" } } } }, "default": { "$ref": "#/components/responses/Problem" } } } },

    "/batch": { "post": { "tags": ["Batch"], "operationId": "batch", "summary": "Run up to 100 record writes in one call (event-silent; metered per op).", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["operations"], "properties": { "operations": { "type": "array", "maxItems": 100, "items": { "type": "object", "properties": { "object": { "type": "string", "enum": ["contact", "company", "deal", "activity"] }, "method": { "type": "string", "enum": ["create", "update", "delete"] }, "data": { "type": "object" }, "patch": { "type": "object" }, "id": { "type": "string" } } } } } } } } }, "responses": { "200": { "description": "Per-op results (partial success)", "content": { "application/json": { "schema": { "type": "object" } } } }, "default": { "$ref": "#/components/responses/Problem" } } } }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": { "type": "http", "scheme": "bearer", "description": "Workspace-scoped API key. relm_live_... (live) or relm_test_... (free, isolated test mode). Mint at https://app.relmcrm.com/." }
    },
    "parameters": {
      "Limit": { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 25, "maximum": 100 }, "description": "Page size (default 25, max 100)." },
      "Cursor": { "name": "cursor", "in": "query", "schema": { "type": "string" }, "description": "Opaque keyset cursor from a prior next_cursor." },
      "IncludeDeleted": { "name": "include_deleted", "in": "query", "schema": { "type": "boolean" }, "description": "Include soft-deleted rows." },
      "IdPath": { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } },
      "IdempotencyKey": { "name": "Idempotency-Key", "in": "header", "schema": { "type": "string" }, "description": "Safely retry a create: same key + same body replays the original result." },
      "IfMatch": { "name": "If-Match", "in": "header", "schema": { "type": "string" }, "description": "The record's current version for optimistic concurrency; a mismatch returns 412 version_conflict." }
    },
    "responses": {
      "Problem": { "description": "RFC-9457 problem+json error.", "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/Problem" } } } }
    },
    "schemas": {
      "Problem": { "type": "object", "description": "RFC-9457 error. Closed-set rejections carry valid_options + suggestion so an agent self-corrects.", "properties": { "type": { "type": "string", "format": "uri", "example": "https://relmcrm.com/errors/unknown_value" }, "title": { "type": "string" }, "status": { "type": "integer" }, "detail": { "type": "string" }, "code": { "type": "string", "example": "unknown_value" }, "field": { "type": "string" }, "valid_options": { "type": "array", "items": { "type": "string" } }, "suggestion": { "type": "string" }, "request_id": { "type": "string" } } },
      "ListMeta": { "type": "object", "properties": { "object": { "type": "string", "const": "list" }, "has_more": { "type": "boolean" }, "next_cursor": { "type": ["string", "null"] } } },
      "Deleted": { "type": "object", "properties": { "id": { "type": "string" }, "object": { "type": "string" }, "deleted": { "type": "boolean" } } },
      "Contact": { "type": "object", "properties": { "id": { "type": "string", "example": "con_..." }, "object": { "type": "string", "const": "contact" }, "first_name": { "type": ["string", "null"] }, "last_name": { "type": ["string", "null"] }, "email": { "type": ["string", "null"] }, "phone": { "type": ["string", "null"] }, "linkedin_url": { "type": ["string", "null"] }, "type": { "type": ["string", "null"] }, "company_id": { "type": ["string", "null"] }, "custom_fields": { "type": "object" }, "version": { "type": "integer" }, "mode": { "type": "string" }, "created_at": { "type": "string" }, "updated_at": { "type": "string" }, "deleted": { "type": "boolean" } } },
      "ContactInput": { "type": "object", "description": "At least one of name / email / phone / linkedin_url / company_id / a custom field.", "properties": { "first_name": { "type": "string" }, "last_name": { "type": "string" }, "email": { "type": "string" }, "phone": { "type": "string" }, "linkedin_url": { "type": "string" }, "type": { "type": "string" }, "company_id": { "type": "string" }, "custom_fields": { "type": "object" } } },
      "ContactList": { "allOf": [ { "$ref": "#/components/schemas/ListMeta" }, { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Contact" } } } } ] },
      "Company": { "type": "object", "properties": { "id": { "type": "string", "example": "cmp_..." }, "object": { "type": "string", "const": "company" }, "name": { "type": "string" }, "domain": { "type": ["string", "null"] }, "custom_fields": { "type": "object" }, "version": { "type": "integer" }, "mode": { "type": "string" }, "created_at": { "type": "string" }, "updated_at": { "type": "string" }, "deleted": { "type": "boolean" } } },
      "CompanyInput": { "type": "object", "required": ["name"], "properties": { "name": { "type": "string" }, "domain": { "type": "string" }, "custom_fields": { "type": "object" } } },
      "CompanyList": { "allOf": [ { "$ref": "#/components/schemas/ListMeta" }, { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Company" } } } } ] },
      "Deal": { "type": "object", "properties": { "id": { "type": "string", "example": "deal_..." }, "object": { "type": "string", "const": "deal" }, "title": { "type": "string" }, "value_cents": { "type": ["integer", "null"], "description": "Integer minor units (cents)." }, "currency": { "type": "string" }, "pipeline": { "type": ["string", "null"], "description": "Pipeline KEY. Every deal carries its pipeline - group/filter by (pipeline, stage), never by stage alone (stage keys are not unique across pipelines)." }, "pipeline_name": { "type": ["string", "null"], "description": "Human display name of the pipeline." }, "stage": { "type": ["string", "null"], "description": "Stage KEY within this deal's pipeline." }, "stage_label": { "type": ["string", "null"], "description": "Human display label of the stage." }, "stage_type": { "type": ["string", "null"], "enum": ["open", "won", "lost", null], "description": "Semantic stage type - use this for won/lost, cross-pipeline, instead of string-matching the key." }, "company_id": { "type": ["string", "null"] }, "primary_contact_id": { "type": ["string", "null"] }, "close_date": { "type": ["string", "null"] }, "custom_fields": { "type": "object" }, "version": { "type": "integer" }, "mode": { "type": "string" }, "created_at": { "type": "string" }, "updated_at": { "type": "string" }, "deleted": { "type": "boolean" } } },
      "DealInput": { "type": "object", "required": ["title"], "properties": { "title": { "type": "string" }, "value_cents": { "type": "integer" }, "currency": { "type": "string" }, "pipeline": { "type": "string", "description": "Pipeline key or pl_ id (defaults to the default pipeline)." }, "stage": { "type": "string", "description": "Stage key within the deal's pipeline." }, "company_id": { "type": "string" }, "primary_contact_id": { "type": "string" }, "close_date": { "type": "string" }, "custom_fields": { "type": "object" } } },
      "DealList": { "allOf": [ { "$ref": "#/components/schemas/ListMeta" }, { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Deal" } } } } ] },
      "Activity": { "type": "object", "properties": { "id": { "type": "string", "example": "act_..." }, "object": { "type": "string", "const": "activity" }, "type": { "type": "string" }, "body": { "type": ["string", "null"] }, "contact_id": { "type": ["string", "null"] }, "deal_id": { "type": ["string", "null"] }, "occurred_at": { "type": "string" }, "custom_fields": { "type": "object" }, "version": { "type": "integer" }, "mode": { "type": "string" }, "created_at": { "type": "string" }, "updated_at": { "type": "string" }, "deleted": { "type": "boolean" } } },
      "ActivityInput": { "type": "object", "description": "Must attach to a contact_id and/or deal_id.", "properties": { "type": { "type": "string", "description": "A registered activity.type (note/email/call/meeting/task/...)." }, "body": { "type": "string" }, "contact_id": { "type": "string" }, "deal_id": { "type": "string" }, "occurred_at": { "type": "string", "description": "ISO datetime; backdates imported history." }, "custom_fields": { "type": "object" } } },
      "ActivityList": { "allOf": [ { "$ref": "#/components/schemas/ListMeta" }, { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Activity" } } } } ] },
      "Pipeline": { "type": "object", "properties": { "id": { "type": "string", "example": "pl_..." }, "object": { "type": "string", "const": "pipeline" }, "key": { "type": "string" }, "name": { "type": "string" }, "is_default": { "type": "boolean" }, "stages": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "key": { "type": "string" }, "label": { "type": "string" }, "ordinal": { "type": "integer" }, "type": { "type": "string", "enum": ["open", "won", "lost"], "description": "Semantic type; default open." } } } } } },
      "PipelineInput": { "type": "object", "properties": { "key": { "type": "string" }, "name": { "type": "string" }, "is_default": { "type": "boolean" }, "stages": { "type": "array", "items": { "type": "object", "properties": { "key": { "type": "string", "description": "Slugified on write (lowercase, [a-z0-9_]); original text kept as label." }, "label": { "type": "string" }, "type": { "type": "string", "enum": ["open", "won", "lost"] } } } } } },
      "AutomationInput": { "type": "object", "required": ["name", "trigger_event", "actions"], "properties": { "name": { "type": "string" }, "trigger_event": { "type": "string", "enum": ["contact.created", "contact.updated", "deal.created", "deal.updated", "deal.stage_changed"] }, "conditions": { "type": "array", "items": { "type": "object", "properties": { "field": { "type": "string" }, "op": { "type": "string" }, "value": {} } } }, "actions": { "type": "array", "items": { "type": "object", "properties": { "type": { "type": "string", "enum": ["send_email", "send_message", "create_activity", "move_deal_stage", "set_field"] } } } }, "enabled": { "type": "boolean" } } },
      "SequenceInput": { "type": "object", "required": ["name", "steps"], "properties": { "name": { "type": "string" }, "channel": { "type": "string" }, "connection": { "type": "string" }, "trigger": { "type": "object" }, "exit_when": { "type": "array" }, "steps": { "type": "array", "items": { "type": "object", "properties": { "wait_days": { "type": "integer" }, "subject": { "type": "string" }, "body": { "type": "string" } } } }, "enroll_existing": { "type": "boolean" }, "enabled": { "type": "boolean" } } },
      "WebhookInput": { "type": "object", "required": ["url"], "properties": { "url": { "type": "string", "format": "uri", "description": "Public https endpoint (test mode allows localhost)." }, "events": { "type": "array", "items": { "type": "string" }, "description": "Subset of the 5 events, or [\"*\"]." }, "description": { "type": "string" }, "enabled": { "type": "boolean" } } },
      "Webhook": { "type": "object", "properties": { "id": { "type": "string", "example": "wh_..." }, "object": { "type": "string", "const": "webhook" }, "url": { "type": "string" }, "events": { "type": "array", "items": { "type": "string" } }, "description": { "type": ["string", "null"] }, "enabled": { "type": "boolean" }, "secret": { "type": "string", "description": "whsec_...; returned ONLY on create." }, "version": { "type": "integer" } } },
      "Usage": { "type": "object", "properties": { "period": { "type": "string" }, "used": { "type": "integer" }, "overage": { "type": "integer" }, "limit": { "type": "integer" }, "plan": { "type": "string" } } },
      "Settings": { "type": "object", "properties": { "overage_cap_usd": { "type": ["number", "null"] } } },
      "SearchResult": { "type": "object", "properties": { "object": { "type": "string", "const": "search" }, "query": { "type": "string" }, "has_more": { "type": "boolean" }, "results": { "type": "array", "items": { "type": "object", "properties": { "type": { "type": "string" }, "id": { "type": "string" }, "title": { "type": "string" } } } } } },
      "SchemaDoc": { "type": "object", "properties": { "objects": { "type": "array", "items": { "type": "object", "properties": { "key": { "type": "string" }, "id_prefix": { "type": ["string", "null"] }, "list_filters": { "type": "array", "items": { "type": "string" } }, "fields": { "type": "array", "items": { "type": "object" } } } } }, "enum_groups": { "type": "object" }, "list_controls": { "type": "array", "items": { "type": "string" } }, "notes": { "type": "object" } } }
    }
  }
}
