Inbound API

01Inbound API reference

Send contacts and tags into Funnels.cm. Every tag request creates or updates the contact for that email, then runs tag automations.

Upsert contact

POST /api/v1/contacts

{
  "email": "[email protected]",
  "firstName": "Jane",
  "lastName": "Doe",
  "phone": "+15551234567",
  "tagIds": ["tagId123"],
  "customFields": { "customFieldId": "Acme Inc" }
}

Use tagNames instead of tagIds if you prefer names: "tagNames": ["Newsletter"].

  • Upsert by email (case-insensitive).
  • tagNames / tagIds on upsert are add-only (existing tags are kept).
  • Unknown tag names are ignored; invalid tag IDs are skipped. Check the tags object in the response.

Response:

{
  "success": true,
  "contact": { "id": "contactId123", "email": "[email protected]", "firstName": "Jane", "tagIds": ["tagId123"] },
  "created": true,
  "tags": {
    "requested": { "tagNames": [], "tagIds": ["tagId123"] },
    "applied": { "tagNames": ["Newsletter"], "tagIds": ["tagId123"] }
  }
}

If no tags matched, the response may include tags.unmatchedTagNames and tags.warning.

List & get contacts

GET /api/v1/[email protected]&limit=50 · GET /api/v1/contacts/:contactId

Tags

GET /api/v1/tags returns { "tags": [{ "id", "name", "order", "createdAt" }, ...] }.

Tag by email - POST /api/v1/contacts/tags

{
  "email": "[email protected]",
  "tagIds": ["tagId123"],
  "action": "add",
  "firstName": "Jane"
}

tagNames works the same way. Send either tagIds or tagNames (or both).

action: "add" (default, upserts contact) or "remove" (requires existing contact).

By contact ID - POST /api/v1/contacts/:contactId/tags · { "tagIds": ["tagId123"], "action": "add" }

CRM leads (optional)

POST /api/v1/crms/:crmId/leads - creates a lead and upserts the contact in one call:

{
  "title": "Inbound demo request",
  "stageId": "stageId123",
  "contactEmail": "[email protected]",
  "firstName": "Jane",
  "tagIds": ["tagId123"]
}

PATCH /api/v1/crms/:crmId/leads/:leadId - update title, stageId, or amount.