iblai-api-crm
Manage an organization's CRM from the API: people and organizations,
pipelines and their stages, lead sources, deals (with stage-move / won / lost
actions), activities, and tags — all the sales and relationship-management
records for one organization. Use for lead capture, pipelines, and deal flow.
Auth & conventions
- Base URL:
https://api.iblai.app/dm — CRM is a Data Manager (DM)
endpoint, so the /dm prefix is required; the /api/crm/... paths below
are appended to it (e.g. https://api.iblai.app/dm/api/crm/persons/).
- Header:
Authorization: Api-Token $IBLAI_API_KEY on every request. (The CRM
developer docs phrase this as Authorization: Token <key> — it is the same
Platform API Token.)
- Scope: Platform-scoped. Every record belongs to the organization resolved
from the token, so there is no
{org} in the path.
- Ids: integers for every resource except Person and Organization, whose
ids are UUID strings.
- Not connected yet? Run
/iblai-api-login first to populate IBLAI_ORG,
IBLAI_USERNAME, and IBLAI_API_KEY.
Resources
| Resource |
Path |
Id |
| Person |
/api/crm/persons/ |
UUID |
| Organization |
/api/crm/organizations/ |
UUID |
| Pipeline |
/api/crm/pipelines/ |
int |
| Stage |
/api/crm/pipelines/{pipeline_id}/stages/ |
int (nested under a pipeline) |
| Lead Source |
/api/crm/lead-sources/ |
int |
| Deal |
/api/crm/deals/ |
int |
| Activity |
/api/crm/activities/ |
int |
| Tag |
/api/crm/tags/ |
int |
Each resource supports standard REST: GET (list), POST (create),
GET {id} (read), PATCH {id} (update), DELETE {id} (delete).
DELETE is destructive — confirm with the user first.
Useful filters
owner={user_id} — "my pipeline" / "my accounts".
owner__isnull=true — unowned records.
?is_default=true on pipelines — the seeded pipeline; its response embeds its
stages inline.
Pagination
List GETs are page-numbered. Navigate with ?page={n} and override the page
size with ?page_size={n} (default 50). The list envelope is:
{ "count": 137, "next_page": 3, "previous_page": 1, "results": [ /* … */ ] }
next_page / previous_page are page numbers (or null at the ends), not
URLs — a detail different from stock DRF pagination.
Reads
Person
- GET
/api/crm/persons/ — list people.
- GET
/api/crm/persons/{id}/ — read a person.
Organization
- GET
/api/crm/organizations/ — list organizations.
- GET
/api/crm/organizations/{id}/ — read an organization.
Pipeline
- GET
/api/crm/pipelines/ — list pipelines.
- GET
/api/crm/pipelines/{id}/ — read a pipeline.
Stage
- GET
/api/crm/pipelines/{pipeline_id}/stages/ — list a pipeline's stages.
- GET
/api/crm/pipelines/{pipeline_id}/stages/{id}/ — read a stage.
Lead Source
- GET
/api/crm/lead-sources/ — list lead sources.
- GET
/api/crm/lead-sources/{id}/ — read a lead source.
Deal
- GET
/api/crm/deals/ — list deals.
- GET
/api/crm/deals/{id}/ — read a deal.
Activity
- GET
/api/crm/activities/ — list activities.
- GET
/api/crm/activities/{id}/ — read an activity.
Tag
- GET
/api/crm/tags/ — list tags.
- GET
/api/crm/tags/{id}/ — read a tag.
Writes
Person
- POST
/api/crm/persons/ — create a person.
- PATCH
/api/crm/persons/{id}/ — update a person.
- DELETE
/api/crm/persons/{id}/ — delete a person. Confirm with the user first.
Person actions:
- POST
/api/crm/persons/merge/ — merge duplicates into one: body
{ "primary_id": UUID, "duplicate_ids": [UUID, …] }; reparents the duplicates'
deals / activities / tags onto the primary. Destructive — confirm first.
- POST
/api/crm/persons/{id}/invite/ — email an invitation to the person's
primary_email. Body (all optional): is_admin (bool), is_staff (bool),
enrollment_config (object, forwarded to auto-enroll the invitee),
redirect_to (url). Success returns the invitation_id; 409 if an active
invitation already exists for that email (the response carries the existing
invitation_id, so you can track / resend it), 422 if the person is already
linked to a platform user. Sends outward — confirm with the user first.
- POST
/api/crm/persons/{id}/link-user/ — link the CRM person to an existing
platform user: body { "user_id": int } (required; the user must already be an
active member of your org, else 403). Sets platform_user.
Organization
- POST
/api/crm/organizations/ — create an organization.
- PATCH
/api/crm/organizations/{id}/ — update an organization.
- DELETE
/api/crm/organizations/{id}/ — delete an organization. Confirm with the user first.
Pipeline
- POST
/api/crm/pipelines/ — create a pipeline.
- PATCH
/api/crm/pipelines/{id}/ — update a pipeline.
- DELETE
/api/crm/pipelines/{id}/ — delete a pipeline. Confirm with the user first.
Stage
- POST
/api/crm/pipelines/{pipeline_id}/stages/ — create a stage.
- PATCH
/api/crm/pipelines/{pipeline_id}/stages/{id}/ — update a stage.
- DELETE
/api/crm/pipelines/{pipeline_id}/stages/{id}/ — delete a stage. Confirm with the user first.
Lead Source
- POST
/api/crm/lead-sources/ — create a lead source.
- PATCH
/api/crm/lead-sources/{id}/ — update a lead source.
- DELETE
/api/crm/lead-sources/{id}/ — delete a lead source. Confirm with the user first.
Deal
- POST
/api/crm/deals/ — create a deal.
- PATCH
/api/crm/deals/{id}/ — update a deal.
- DELETE
/api/crm/deals/{id}/ — delete a deal. Confirm with the user first.
Deal actions (the canonical way to transition deals):
- PATCH
/api/crm/deals/{id}/ — reposition stage within a pipeline (allowed).
- POST
/api/crm/deals/{id}/move-stage/ — transition stage; body accepts
stage_code (preferred) or stage_id.
- POST
/api/crm/deals/{id}/won/ — close the deal as won. Body optional:
stage_code to target a specific is_won stage (defaults to the pipeline's
first is_won stage by sort_order).
- POST
/api/crm/deals/{id}/lost/ — close the deal as lost. Body requires
a non-empty lost_reason (≤255; 400 if missing); optional stage_code
(defaults to the first is_lost stage).
Activity
- POST
/api/crm/activities/ — create an activity.
- PATCH
/api/crm/activities/{id}/ — update an activity.
- DELETE
/api/crm/activities/{id}/ — delete an activity. Confirm with the user first.
- POST
/api/crm/activities/{id}/done/ — mark the activity done (stamps done_at; see is_done/done_at in the schema).
Tag
- POST
/api/crm/tags/ — create a tag.
- PATCH
/api/crm/tags/{id}/ — update a tag.
- DELETE
/api/crm/tags/{id}/ — delete a tag. Cascades — removes every
assignment on every person / organization / deal. Confirm with the user first.
Attach / detach on a host ({host} = persons | organizations | deals;
both need Ibl.CRM/Tags/write, a separate RBAC bucket from host-write — see
references/workflows.md § Tagging):
- POST
/api/crm/{host}/{id}/tags/ — attach an existing tag to a host record:
body { "tag_id": int } (≥ 1). Returns 201 with { assignment_id, tag };
409 if already attached (idempotent — carries the existing assignment_id, so
treat it as success); 404 if the tag isn't in your org.
- DELETE
/api/crm/{host}/{id}/tags/{tag_id}/ — detach a tag (removes the
assignment row, not the tag). 204 on success; 404 if it wasn't attached. Not
idempotent — a repeat DELETE returns 404; treat that as a no-op success.
Example
Create a person:
curl -X POST \
"https://api.iblai.app/dm/api/crm/persons/" \
-H "Authorization: Api-Token $IBLAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Ada Lovelace",
"primary_email": "ada@example.com",
"lifecycle_stage": "lead"
}'
Notes
- CRM is served via the DM gateway at
https://api.iblai.app/dm/api/crm/
(equivalent to the legacy https://platform.iblai.app/api/crm/ host; skills
standardize on the api.iblai.app/dm form).
- Lifecycle stages are
lead | qualified | opportunity | customer | churned.
- A CRM Person auto-links to a Platform user when a signup matches by email.
- Stages are nested under a pipeline; deal transitions go through the deal
actions (
move-stage/, won/, lost/) rather than ad-hoc edits.
- Every read is scoped to your org (the token's
platform), so a record in
another org returns 404, not 403 — existence is never leaked. Treat 404
as "not found or not visible to you".
Schema
Field-level request/response shape (Mode req/opt/ro) for every resource, plus the
enums and the confirmed filter query params, live in a reference file to keep this skill
scannable: references/schema.md. Read it when you need exact
field names, types, defaults, or which filters a list GET accepts.
Reference material
The endpoints and field schemas above are the authoritative, code-verified surface. These
companion files (ported from the CRM developer guide) preserve the surrounding concepts,
workflows, and guidance — read them for depth, not for endpoint truth:
references/schema.md — field-level request/response shape (Mode req/opt/ro), enums, and the confirmed filter query params for every resource.
references/guide.md — concepts & data model: system overview, write side-effects, the deal-status state machine, auth/security notes, the object graph, the resource map, and per-resource deletion/cascade behavior.
references/quickstart.md — end-to-end worked walkthrough: capture a lead, find the seeded pipeline, open a deal, move it through stages, and close it won.
references/workflows.md — subsystem lifecycles: person onboarding (link / invite / merge / auto-link), deal lifecycle, activity timeline & auto-records, tagging, and CRM notifications (cross-refs /iblai-api-notification).
references/operations.md — filtering & pagination, the RBAC role/permission matrix (cross-refs /iblai-api-rbac), the error reference, and best practices.
1---2name: iblai-api-crm3description: Manage an ibl.ai organization's CRM via the platform API — people, organizations, pipelines and stages, lead sources, deals (with stage-move/won/lost actions), activities, and tags. Org-wide sales/relationship management. Use for lead capture, pipelines, and deal flow.4---56# iblai-api-crm78Manage an organization's **CRM** from the API: people and organizations,9pipelines and their stages, lead sources, deals (with stage-move / won / lost10actions), activities, and tags — all the sales and relationship-management11records for one organization. Use for lead capture, pipelines, and deal flow.1213## Auth & conventions1415- **Base URL:** `https://api.iblai.app/dm` — CRM is a Data Manager (DM)16 endpoint, so the **`/dm` prefix is required**; the `/api/crm/...` paths below17 are appended to it (e.g. `https://api.iblai.app/dm/api/crm/persons/`).18- **Header:** `Authorization: Api-Token $IBLAI_API_KEY` on every request. (The CRM19 developer docs phrase this as `Authorization: Token <key>` — it is the same20 Platform API Token.)21- **Scope:** Platform-scoped. Every record belongs to the organization resolved22 from the token, so there is **no `{org}` in the path**.23- **Ids:** integers for every resource **except** Person and Organization, whose24 ids are **UUID** strings.25- Not connected yet? Run **`/iblai-api-login`** first to populate `IBLAI_ORG`,26 `IBLAI_USERNAME`, and `IBLAI_API_KEY`.2728## Resources2930| Resource | Path | Id |31| ------------ | ----------------------------------------- | ------------------------------- |32| Person | `/api/crm/persons/` | UUID |33| Organization | `/api/crm/organizations/` | UUID |34| Pipeline | `/api/crm/pipelines/` | int |35| Stage | `/api/crm/pipelines/{pipeline_id}/stages/` | int (nested under a pipeline) |36| Lead Source | `/api/crm/lead-sources/` | int |37| Deal | `/api/crm/deals/` | int |38| Activity | `/api/crm/activities/` | int |39| Tag | `/api/crm/tags/` | int |4041Each resource supports standard REST: **GET** (list), **POST** (create),42**GET** `{id}` (read), **PATCH** `{id}` (update), **DELETE** `{id}` (delete).43DELETE is destructive — confirm with the user first.4445### Useful filters4647- `owner={user_id}` — "my pipeline" / "my accounts".48- `owner__isnull=true` — unowned records.49- `?is_default=true` on pipelines — the seeded pipeline; its response embeds its50 stages inline.5152## Pagination5354List `GET`s are page-numbered. Navigate with `?page={n}` and override the page55size with `?page_size={n}` (default `50`). The list envelope is:5657```json58{ "count": 137, "next_page": 3, "previous_page": 1, "results": [ /* … */ ] }59```6061`next_page` / `previous_page` are page **numbers** (or `null` at the ends), not62URLs — a detail different from stock DRF pagination.6364## Reads6566### Person6768- **GET** `/api/crm/persons/` — list people.69- **GET** `/api/crm/persons/{id}/` — read a person.7071### Organization7273- **GET** `/api/crm/organizations/` — list organizations.74- **GET** `/api/crm/organizations/{id}/` — read an organization.7576### Pipeline7778- **GET** `/api/crm/pipelines/` — list pipelines.79- **GET** `/api/crm/pipelines/{id}/` — read a pipeline.8081### Stage8283- **GET** `/api/crm/pipelines/{pipeline_id}/stages/` — list a pipeline's stages.84- **GET** `/api/crm/pipelines/{pipeline_id}/stages/{id}/` — read a stage.8586### Lead Source8788- **GET** `/api/crm/lead-sources/` — list lead sources.89- **GET** `/api/crm/lead-sources/{id}/` — read a lead source.9091### Deal9293- **GET** `/api/crm/deals/` — list deals.94- **GET** `/api/crm/deals/{id}/` — read a deal.9596### Activity9798- **GET** `/api/crm/activities/` — list activities.99- **GET** `/api/crm/activities/{id}/` — read an activity.100101### Tag102103- **GET** `/api/crm/tags/` — list tags.104- **GET** `/api/crm/tags/{id}/` — read a tag.105106## Writes107108### Person109110- **POST** `/api/crm/persons/` — create a person.111- **PATCH** `/api/crm/persons/{id}/` — update a person.112- **DELETE** `/api/crm/persons/{id}/` — delete a person. Confirm with the user first.113114**Person actions:**115116- **POST** `/api/crm/persons/merge/` — merge duplicates into one: body117 `{ "primary_id": UUID, "duplicate_ids": [UUID, …] }`; reparents the duplicates'118 deals / activities / tags onto the primary. Destructive — confirm first.119- **POST** `/api/crm/persons/{id}/invite/` — email an invitation to the person's120 `primary_email`. Body (all optional): `is_admin` (bool), `is_staff` (bool),121 `enrollment_config` (object, forwarded to auto-enroll the invitee),122 `redirect_to` (url). Success returns the `invitation_id`; `409` if an active123 invitation already exists for that email (the response carries the existing124 `invitation_id`, so you can track / resend it), `422` if the person is already125 linked to a platform user. Sends outward — confirm with the user first.126- **POST** `/api/crm/persons/{id}/link-user/` — link the CRM person to an existing127 platform user: body `{ "user_id": int }` (required; the user must already be an128 active member of your org, else `403`). Sets `platform_user`.129130### Organization131132- **POST** `/api/crm/organizations/` — create an organization.133- **PATCH** `/api/crm/organizations/{id}/` — update an organization.134- **DELETE** `/api/crm/organizations/{id}/` — delete an organization. Confirm with the user first.135136### Pipeline137138- **POST** `/api/crm/pipelines/` — create a pipeline.139- **PATCH** `/api/crm/pipelines/{id}/` — update a pipeline.140- **DELETE** `/api/crm/pipelines/{id}/` — delete a pipeline. Confirm with the user first.141142### Stage143144- **POST** `/api/crm/pipelines/{pipeline_id}/stages/` — create a stage.145- **PATCH** `/api/crm/pipelines/{pipeline_id}/stages/{id}/` — update a stage.146- **DELETE** `/api/crm/pipelines/{pipeline_id}/stages/{id}/` — delete a stage. Confirm with the user first.147148### Lead Source149150- **POST** `/api/crm/lead-sources/` — create a lead source.151- **PATCH** `/api/crm/lead-sources/{id}/` — update a lead source.152- **DELETE** `/api/crm/lead-sources/{id}/` — delete a lead source. Confirm with the user first.153154### Deal155156- **POST** `/api/crm/deals/` — create a deal.157- **PATCH** `/api/crm/deals/{id}/` — update a deal.158- **DELETE** `/api/crm/deals/{id}/` — delete a deal. Confirm with the user first.159160**Deal actions** (the canonical way to transition deals):161162- **PATCH** `/api/crm/deals/{id}/` — reposition `stage` within a pipeline (allowed).163- **POST** `/api/crm/deals/{id}/move-stage/` — transition stage; body accepts164 `stage_code` (preferred) or `stage_id`.165- **POST** `/api/crm/deals/{id}/won/` — close the deal as won. Body optional:166 `stage_code` to target a specific `is_won` stage (defaults to the pipeline's167 first `is_won` stage by `sort_order`).168- **POST** `/api/crm/deals/{id}/lost/` — close the deal as lost. Body **requires**169 a non-empty `lost_reason` (≤255; `400` if missing); optional `stage_code`170 (defaults to the first `is_lost` stage).171172### Activity173174- **POST** `/api/crm/activities/` — create an activity.175- **PATCH** `/api/crm/activities/{id}/` — update an activity.176- **DELETE** `/api/crm/activities/{id}/` — delete an activity. Confirm with the user first.177- **POST** `/api/crm/activities/{id}/done/` — mark the activity done (stamps `done_at`; see `is_done`/`done_at` in the schema).178179### Tag180181- **POST** `/api/crm/tags/` — create a tag.182- **PATCH** `/api/crm/tags/{id}/` — update a tag.183- **DELETE** `/api/crm/tags/{id}/` — delete a tag. Cascades — removes every184 assignment on every person / organization / deal. Confirm with the user first.185186**Attach / detach on a host** (`{host}` = `persons` | `organizations` | `deals`;187both need `Ibl.CRM/Tags/write`, a **separate** RBAC bucket from host-write — see188[`references/workflows.md`](references/workflows.md) § Tagging):189190- **POST** `/api/crm/{host}/{id}/tags/` — attach an existing tag to a host record:191 body `{ "tag_id": int }` (`≥ 1`). Returns `201` with `{ assignment_id, tag }`;192 `409` if already attached (idempotent — carries the existing `assignment_id`, so193 treat it as success); `404` if the tag isn't in your org.194- **DELETE** `/api/crm/{host}/{id}/tags/{tag_id}/` — detach a tag (removes the195 assignment row, not the tag). `204` on success; `404` if it wasn't attached. Not196 idempotent — a repeat DELETE returns `404`; treat that as a no-op success.197198## Example199200Create a person:201202```bash203curl -X POST \204 "https://api.iblai.app/dm/api/crm/persons/" \205 -H "Authorization: Api-Token $IBLAI_API_KEY" \206 -H "Content-Type: application/json" \207 -d '{208 "name": "Ada Lovelace",209 "primary_email": "ada@example.com",210 "lifecycle_stage": "lead"211 }'212```213214## Notes215216- CRM is served via the DM gateway at `https://api.iblai.app/dm/api/crm/`217 (equivalent to the legacy `https://platform.iblai.app/api/crm/` host; skills218 standardize on the `api.iblai.app/dm` form).219- Lifecycle stages are `lead | qualified | opportunity | customer | churned`.220- A CRM Person auto-links to a Platform user when a signup matches by email.221- Stages are nested under a pipeline; deal transitions go through the deal222 actions (`move-stage/`, `won/`, `lost/`) rather than ad-hoc edits.223- Every read is scoped to your org (the token's `platform`), so a record in224 another org returns `404`, not `403` — existence is never leaked. Treat `404`225 as "not found **or** not visible to you".226227## Schema228229Field-level request/response shape (**Mode** `req`/`opt`/`ro`) for every resource, plus the230enums and the confirmed filter query params, live in a reference file to keep this skill231scannable: **[`references/schema.md`](references/schema.md)**. Read it when you need exact232field names, types, defaults, or which filters a list `GET` accepts.233234## Reference material235236The endpoints and field schemas above are the authoritative, code-verified surface. These237companion files (ported from the CRM developer guide) preserve the surrounding concepts,238workflows, and guidance — read them for depth, not for endpoint truth:239240- **[`references/schema.md`](references/schema.md)** — field-level request/response shape (**Mode** `req`/`opt`/`ro`), enums, and the confirmed filter query params for every resource.241- **[`references/guide.md`](references/guide.md)** — concepts & data model: system overview, write side-effects, the deal-status state machine, auth/security notes, the object graph, the resource map, and per-resource deletion/cascade behavior.242- **[`references/quickstart.md`](references/quickstart.md)** — end-to-end worked walkthrough: capture a lead, find the seeded pipeline, open a deal, move it through stages, and close it won.243- **[`references/workflows.md`](references/workflows.md)** — subsystem lifecycles: person onboarding (link / invite / merge / auto-link), deal lifecycle, activity timeline & auto-records, tagging, and CRM notifications (cross-refs `/iblai-api-notification`).244- **[`references/operations.md`](references/operations.md)** — filtering & pagination, the RBAC role/permission matrix (cross-refs `/iblai-api-rbac`), the error reference, and best practices.