# Auto Appy CRM API Source-checked on 2026-09-22. This guide describes the checked-out implementation; deployment may be older. Backend revision before documentation: `050b0d3`. ## Authentication and independent use These APIs can be called from any server-side HTTP client; no workflow node, integration template, or Gemini call is required. Use the API host below, not the product website. The examples use fictional records and placeholders. No request shown here was sent to production during this implementation. Create an application-specific API key through the signed-in app's **API keys** page. Supply `Authorization: Bearer `, `Accept: application/json`, and `X-AutoAppy-Workspace: `. Add `Content-Type: application/json` for JSON writes. The key is a personal credential: current application access, organisation membership and resource permissions still apply. Use a read/write key for writes; a read-only key does not become writable by selecting an organisation. Keys cannot create more keys or bypass interactive management restrictions. Set finite client timeouts, keep TLS verification enabled, and do not follow redirects with credentials. Store the key in a server-side environment/secret store. The Postman collection has an empty `api_key` variable; set it locally as a secret. Do not export it after adding a key. The collection contains writes: send only the requests you intend to execute; do not run the whole collection against production. ## Errors and debugging | Result | Meaning / next check | | --- | --- | | 200 / 201 | API read/create accepted; inspect business status in the response. | | 202 | Work accepted asynchronously, not finished. Read its status/result. | | 401 | Missing, invalid, expired or revoked credential; wrong auth mechanism may also cause this. | | 403 | Wrong application key, read-only write, missing membership, role, record access, or interactive-only endpoint. | | 404 | Wrong local ID or inaccessible record. Do not substitute an ID from another organisation. | | 409 | Version conflict or incompatible repeated operation. Fetch current state before deciding how to proceed. | | 413 / 422 | Payload bounds or validation failure. Inspect the direct API's `message` and `errors`. | | 429 | Rate limit. Honor `Retry-After` when present. Do not automatically repeat a write. | | 5xx / timeout | Dependency or server failure; a write may already have happened. Inspect state before retrying. | Central API key checks allow up to 120 requests/minute/key by default; module validation and platform subrequests consume additional calls. Endpoint-specific limits and AI orchestration limits also apply. A successful request is not proof of WhatsApp delivery or of completed AI processing. To isolate a bug: 1. Call the documented read endpoint directly with the same app key, central organisation and resource IDs. Record method, path, timestamp, status and a redacted response. 2. Compare with this guide and the endpoint's linked controller/request validator. If the documented contract disagrees with deployed code, record both revisions and correct the contract or implementation deliberately. 3. If direct API succeeds but the workflow fails, compare the mapped input, saved connection tag, selected action name, path/query/body mapping, and source API host. Never paste a key into an issue or application log. 4. If the API accepts work but the result is wrong, inspect the owning app's job/message/turn history and downstream provider status. The integration must preserve these distinctions. The [route reference](ROUTES.md), [OpenAPI specification](openapi.json) and [Postman collection](postman_collection.json) describe native application operations independently of the workflow catalog. [Coverage](coverage.json) accounts for included operations and exclusions. [Lookup recipes](lookup-guide.md) provide field descriptions, pagination, complete requests, responses and error handling. Third-party adapter endpoints are internal-only and absent from all public downloads. Sensitive control-plane endpoints are excluded; the exact internal audit remains in the repository. Browser-only product routes are explicitly marked and do not imply API-key access; SSO and CSRF requirements remain enforced. ## Endpoint and workspace contract API root: `https://crmapi.autoappy.com`. Website: `https://crm.autoappy.com`. Key application: `crm`. There is no automatic `/api` prefix. Call `GET /api/auth/me` with `X-AutoAppy-Workspace` (central organisation UUID). The response includes `data.current_workspace`, `data.local_workspace_id`, `workspace_role` and `permissions`. Use the resulting local UUID in `X-Workspace-ID` on subsequent requests as well as retaining the central organisation header. Do not send a central UUID in a local-resource path. A mismatch or unavailable mapping must be repaired through the signed-in organisation connection. ```sh curl --fail-with-body 'https://crmapi.autoappy.com/leads?page=1&per_page=25' \ -H "Authorization: Bearer $CRM_API_KEY" \ -H "X-AutoAppy-Workspace: $AUTOAPPY_ORGANISATION_ID" \ -H "X-Workspace-ID: $CRM_LOCAL_WORKSPACE_ID" -H 'Accept: application/json' ``` ## Leads | Method and path | Contract | | --- | --- | | `GET /leads` | Visible leads only. `page>=1`, `per_page=1..100`, optional `search` (max255), pipeline/stage/assignment/date filters and sorting. Returns resource `data[]`, paginator `links`/`meta`, and `view_counts`. | | `GET /leads/{lead}` | One accessible lead, in `data`. Lead IDs are integers. | | `POST /leads` | Create a lead. `name` is required, max255. Returns the created lead resource. | | `PUT /leads/{lead}` | Partial update. Omitted fields stay unchanged; supplied nullable fields can be cleared. `lead_stage_id` and `stage_changed_at` are prohibited here. | Common optional strings: `email` (valid email), `phone`, `company`, `website`, `designation`, `company_location`, `team_size`, `revenue`, `source`, `priority_area`, `priority_area_type`. String bounds are 255 characters. `assigned_user_id` is an authorized local user UUID. `additional_details` is a list of up to 50 `{key,value}` pairs, with distinct keys up to100 and values up to2000 characters. `custom_fields` is a keyed object/array with at most100 entries. Create can include `lead_stage_id` (an integer belonging to the workspace); it determines the pipeline for validation. Selecting a pipeline for discovery is not itself a move operation. Create example: ```json {"name":"Example customer","email":"customer@example.invalid","company":"Example Ltd","lead_stage_id":12,"custom_fields":{"budget":25000,"consent":false}} ``` The custom keys and stage are illustrative: discover your own definitions first. Members may be automatically assigned to themselves. Assigned user, lead visibility and pipeline access are checked by the backend. ## Dynamic field discovery and pipelines - `GET /admin/pipelines/pipelines` returns `{success:true,data:[...]}` with pipeline UUIDs and names. - `GET /admin/pipelines/stages?pipeline_id={uuid}` returns stage integer IDs, names and order for an accessible pipeline. - `GET /workspaces/{workspace}/lead-fields?pipeline_id={uuid}` returns `data[]` definitions. The filter includes global fields plus selected-pipeline fields. Without the filter, the API lists active workspace definitions, so a caller must still apply the relevant pipeline context before writing. A field definition exposes `key`, `label`, `field_type`, `options`, `is_required`, `is_active`, `pipeline_id`, `validation_rules` and other presentation metadata. Send the stable `key` under `custom_fields`; labels are not API keys. Checkbox values should be JSON booleans; multiselect values are arrays of configured option values; numeric/currency fields must be numeric. Archived/unknown fields and invalid options are rejected. Use an existing lead's actual pipeline when editing its custom fields. Stage changes use the dedicated `lead-workflow` endpoints. Pipeline/stage/node/transition authoring is restricted by workflow management permissions. Document storage and uploads, lead documents, activities, analytics, team performance, owner assignment and imports are separate API families; see the complete reference and linked request classes. Document upload completion has its own lifecycle and should not be treated as a single lead edit. ## Activity logging and follow-ups `POST /lead-activities` accepts integer `lead_id`, required `type` (CALL, EMAIL, WHATSAPP, MEETING, NOTE or FOLLOWUP), optional `status` (PENDING, COMPLETED or CANCELLED), `note` (up to 10,000 characters), `response_type`, `scheduled_at` and `meta`. Omitted status means COMPLETED; explicitly choose PENDING to schedule a follow-up. Example: ```json {"lead_id":123,"type":"FOLLOWUP","status":"PENDING","note":"Call after the demo","scheduled_at":"2026-09-23T10:00:00Z"} ``` `PATCH /lead-activities/{leadActivity}/complete` marks an accessible activity completed with the current completion time; no request body is needed. Both enforce current workspace and activity permissions. Logging EMAIL or WHATSAPP records an activity; it does not deliver a message. Lead workflow transitions have separate state-machine requirements and are documented in the full route reference rather than offered as a generic stage overwrite. The curated workflow picker exposes lead find/get/create/update and activity create/complete; pipeline, team and organisation configuration remain product setup. ## Pipeline lead columns (24 September 2026) Before creating a lead, read `GET /workspaces/{workspace}/lead-fields/schema?pipeline_id={pipeline}` for enabled starter columns, then `GET /workspaces/{workspace}/lead-fields?pipeline_id={pipeline}` for typed custom fields. Send starter keys at the top level and custom keys inside `custom_fields`. Omit disabled starter keys, including empty/null values. Select a stage belonging to that pipeline; the existing create API derives the actual pipeline from `lead_stage_id`, not `pipeline_id`. Partial lead updates keep the existing pipeline; stage changes use the workflow APIs. HTTP 422 returns field-specific `errors`.