Skip to main content

API Endpoints Reference

Written by Semira K

This document covers every available endpoint in the DmTracker API. For authentication and general setup, see API Overview & Authentication.


Endpoints at a Glance

#

Endpoint

Method

Purpose

1

/contact/default-reply

POST

ManyChat default reply webhook

2

/organization/create-contact

POST

Create or update a contact

3

/contact/update-tags-external

POST

Update contact tags by name

4

/contact/contact-status

PATCH

Update lead status and/or pipeline stage


1. Handle Incoming DM Replies

POST /contact/default-reply

Auth: x-org-auth-token header

When to Use This

You're using ManyChat (or a similar tool) and someone replies to your automated DM. This endpoint tells DmTracker: "Hey, this person just replied — track it."

What It Does

  • If the contact already exists → updates their last message and resets follow-up tracking

  • If the contact is new → creates them automatically

  • Marks them as needing follow-up so they show up in your dashboard

Request Body

{
  "manychat_id": "##{{subscriber_id}}",
  "username": "##{{instagram_username}}",
  "organization_id": "your-org-id",
  "message_content": "##{{last_input_text}}",
  "page_name": "##{{page_name}}"
}

Field Descriptions

Field

Type

Required

Description

manychat_id

string

Yes

Unique ManyChat subscriber ID

username

string

Yes

Instagram username (auto-normalized: lowercase, trimmed, @ stripped)

organization_id

UUID

Yes*

*Can be omitted if page_name is provided (resolved via DB lookup)

message_content

string

Yes

The reply message text. If null, empty, or ##{{last_input_text}}, treated as outreach and skipped

message_date

ISO 8601

No

Timestamp of the message. Defaults to current time

page_name

string

No

ManyChat page name. Used to resolve organization_id and update the org's page_name field

ig_id

number

No

Instagram user ID. Can also be passed inside manychat_data.ig_id

manychat_data

object

No

Additional ManyChat metadata. ig_id falls back to manychat_data.ig_id if not set at top level

Note: message_date defaults to now if not provided.

Success Response (200)

{
  "status": "success",
  "message": "Contact processed successfully",
  "data": {
    "manychat_id": "123456",
    "username": "john_doe",
    "organization_id": "a1b2c3d4-...",
    "created_at": "2025-01-12T10:00:00.000Z",
    "last_response_at": "2025-01-12T10:30:00.000Z",
    "last_message_content": "Sure, send me more details about pricing.",
    "contact_type": "outreach",
    "outreach_reason": "New Follower",
    "outreach_message": "Hey, thanks for following!"
  }
}

Note: The response includes contact_type ("outreach" or "inbound"), outreach_reason, and outreach_message fields. These are useful for routing contacts in ManyChat automations.

Error Codes

Status

Cause

400

Missing required fields (manychat_id, username, organization_id or page_name)

401

Invalid or missing x-org-auth-token

405

Non-POST request

500

Internal server error

503

Database infrastructure error (try again later)


2. Create or Update a Contact

POST /organization/create-contact

Auth: x-org-auth-token header
Rate limit: 60 requests per minute per organization

When to Use This

  • Import leads from another tool (spreadsheet, CRM, scraper)

  • Build a custom integration that pushes contacts into DmTracker

  • Log outreach you sent to someone

Two Modes: Inbound vs. Outreach

When creating a contact, you tell DmTracker whether this person reached out to you (inbound) or you reached out to them (outreach) using the had_outreach field.

Inbound — Someone Messaged You First

{
  "organization_id": "your-org-id",
  "username": "john_doe",
  "had_outreach": false,
  "last_response_at": "2025-01-12T10:00:00.000Z",
  "last_message_content": "Hey, I saw your post about coaching!",
  "tags": ["interested", "coaching"],
  "note": "Came from Reel about mindset"
}

Outreach — You Messaged Them First

{
  "organization_id": "your-org-id",
  "username": "prospect_user",
  "had_outreach": true,
  "outreach_reason": "Cold outreach — Q1 campaign",
  "outreach_text": "Hey! Loved your content, would love to connect.",
  "outreach_reason_label": "Q1 Campaign",
  "outreach_message_label": "Intro Message",
  "tags": ["outreach", "q1-campaign"]
}

All Available Fields

Field

Type

Required

Description

organization_id

UUID

Yes

Your organization ID

username

string

Yes

Instagram username (1-30 chars, normalized: lowercase, trimmed, @ stripped)

had_outreach

boolean

Yes

false = inbound, true = outreach

last_response_at

ISO 8601

If inbound

Required when had_outreach=false. Cannot be set when had_outreach=true

last_message_content

string

If inbound

Required when had_outreach=false. Cannot be set when had_outreach=true

outreach_reason

string

If outreach

Required when had_outreach=true. Cannot be set when had_outreach=false

outreach_text

string

If outreach

Required when had_outreach=true. Cannot be set when had_outreach=false

outreach_reason_label

string

No

Label for the outreach reason (for analytics)

outreach_message_label

string

No

Label for the outreach message (for A/B testing)

email

string

No

Resolves created_by_user_id. Must be valid format. User must be org member

manychat_id

string

No

ManyChat subscriber ID

ig_id

number

No

Instagram user ID

activate_followups

boolean

No

Default: true. Set to false to skip follow-up tracking

note

string

No

Max 1000 chars. Stored in contact notes

tags

string[]

No

Array of tag names. Tags are auto-created if they don't exist in the org

tag_color

string

No

Color name for newly created tags. Default: gray. See color reference below

What Happens If the Contact Already Exists?

Scenario

Behavior

HTTP Code

Contact exists (active, same type)

Returns existing contact as-is (updates ig_id if changed)

200

Contact exists (active, inbound) + request is outreach

Converts to outreach, preserves conversation history

200

Contact doesn't exist

Creates new contact

201

Org subscription cancelled

Returns success, no processing

200

Success Response (201 Created)

{
  "status": "success",
  "message": "Contact created successfully",
  "data": {
    "id": "contact-uuid",
    "manychat_id": "MC_123456789",
    "username": "john_doe",
    "organization_id": "a1b2c3d4-...",
    "created_at": "2025-01-12T10:00:00.000Z",
    "last_response_at": "2025-01-12T10:00:00.000Z",
    "last_message_content": "Hello, I'm interested",
    "follow_up_needed": true,
    "had_outreach": false,
    "contact_ingestion_type": "custom-api-import",
    "created_by_user_id": "user-uuid",
    "pipeline_stage": "open"
  }
}

Error Codes

Status

Cause

400

Missing/invalid required fields, validation errors, type mismatch

401

Invalid x-org-auth-token

403

User (from email) is not a member of the organization

404

User with provided email not found

405

Non-POST request

429

Rate limit exceeded (60 requests/minute per org)

500

Server error


3. Update Contact Tags

POST /contact/update-tags-external

Auth: x-org-auth-token header

When to Use This

  • Automatically label leads based on behavior (e.g., tag as "hot-lead" when they click a link)

  • Segment contacts from an external workflow or automation

  • Clean up tags by removing outdated ones

Request Body

{
  "organization_id": "your-org-id",
  "username": "john_doe",
  "mode": "add",
  "tag_names": ["hot-lead", "clicked-link"],
  "tag_color": "red"
}

Field Descriptions

Field

Type

Required

Description

organization_id

UUID

Yes

Validated via x-org-auth-token

contact_id

UUID

Yes*

*Either contact_id or username required

username

string

Yes*

*Either contact_id or username required. Looked up as lowercase

mode

string

Yes

set, add, or remove

tag_names

string[]

Yes

Array of tag name strings

tag_color

string

No

Color name for auto-created tags. Default: gray

email

string

No

Resolves user for audit logging. Must be valid format and org member

Mode Behavior

Mode

What It Does

Auto-creates missing tags?

set

Removes all existing tags, then applies the provided ones

Yes

add

Adds tags to existing ones (skips already-applied tags)

Yes

remove

Removes specified tags from the contact

No (returns 400 if tag name not found)

Success Response (200)

{
  "status": "success",
  "message": "Tags added successfully",
  "data": {
    "contact_id": "contact-uuid",
    "username": "john_doe",
    "tags": [
      { "id": 1, "name": "hot-lead", "color": "#dc2626" },
      { "id": 2, "name": "clicked-link", "color": "#dc2626" }
    ]
  }
}


4. Update Lead Status & Pipeline Stage

PATCH /contact/contact-status

Auth: x-org-auth-token header

When to Use This

When a lead's status changes in your automation flow — for example, marking a lead as "won" after they purchase, or moving them to a different pipeline stage based on their actions.

What It Does

  • Updates a contact's lead status (open, won, lost, abandoned)

  • Moves a contact to a different pipeline stage

  • Can update status, pipeline stage, or both in a single call

  • Triggers smart automations if configured

  • Creates an activity log entry (marked as "via API")

Request Body

{
  "organization_id": "abc-123-...",
  "manychat_id": "12345678",
  "lead_status": "won",
  "pipeline_stage": "Closed"
}

Field Descriptions

Field

Type

Required

Description

organization_id

UUID

Yes

Always required

contact_id

UUID

One of these

DmTracker contact ID. Use this or manychat_id

manychat_id

string

One of these

ManyChat subscriber ID. Use this or contact_id

lead_status

string

At least one*

Status name: open, won, lost, abandoned

lead_status_id

number

At least one*

Status ID number. Use this OR lead_status, not both

pipeline_stage

string

At least one*

Pipeline stage name. Must match an active stage in your organization

*You must include at least one of lead_status, lead_status_id, or pipeline_stage.

Note: This endpoint uses PATCH instead of POST. Make sure your HTTP client sends a PATCH request.

Success Response (200)

{
  "status": "success",
  "data": {
    "id": "contact-uuid",
    "username": "johndoe",
    "lead_status": "won",
    "pipeline_stage": "Closed"
  }
}

Error Codes

Status

Cause

400

Missing required fields or invalid status/stage value

401

Invalid or missing x-org-auth-token

404

Contact not found with the given contact_id or manychat_id

500

Internal server error


Tag Color Reference

When using tag_color in create-contact or update-tags-external, you can use any of these color names:

Name

Hex

red

#dc2626

blue

#2563eb

green

#16a34a

yellow

#ca8a04

purple

#9333ea

pink

#db2777

indigo

#4f46e5

orange

#ea580c

teal

#0d9488

cyan

#0891b2

gray

#374151

slate

#475569

amber

#d97706

lime

#65a30d

emerald

#059669

sky

#0284c7

violet

#7c3aed

fuchsia

#c026d3

rose

#e11d48

You can also pass a hex code directly (e.g., "#FF5733"). Unrecognized names default to gray (#374151).


Code Examples

Create an Outreach Contact (Node.js)

const response = await fetch(
  "https://app.dmtracker.ai/api/v1/organization/create-contact",
  {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "x-org-auth-token": process.env.DMTRACKER_ORG_TOKEN,
    },
    body: JSON.stringify({
      organization_id: "your-org-id",
      username: "newlead",
      had_outreach: true,
      outreach_reason: "Q1 Campaign",
      outreach_text: "Hey! Loved your content.",
      tags: ["outreach", "q1"],
    }),
  }
);const data = await response.json();
console.log(data);

Update Tags (Python)

import requestsresponse = requests.post(
    "https://app.dmtracker.ai/api/v1/contact/update-tags-external",
    headers={
        "Content-Type": "application/json",
        "x-org-auth-token": "your-org-auth-token",
    },
    json={
        "organization_id": "your-org-id",
        "username": "janedoe",
        "mode": "add",
        "tag_names": ["priority", "hot-lead"],
        "tag_color": "red",
    },
)print(response.json())

Update Lead Status & Pipeline Stage (cURL)

curl -X PATCH https://app.dmtracker.ai/api/v1/contact/contact-status \
  -H "Content-Type: application/json" \
  -H "x-org-auth-token: your-org-auth-token" \
  -d '{
    "organization_id": "your-org-id",
    "manychat_id": "12345678",
    "lead_status": "won",
    "pipeline_stage": "Closed"
  }'


Error Handling

All endpoints return clear error messages in a consistent format:

{
  "error": "Error type",
  "message": "A human-readable description of what went wrong."
}

Code

Meaning

400

Bad Request — missing fields, invalid values, or malformed JSON

401

Unauthorized — missing or invalid auth token

403

Forbidden — user not a member of the organization

404

Not Found — contact or endpoint doesn't exist

405

Method Not Allowed — wrong HTTP method

429

Rate Limit — too many requests (wait and retry)

500

Server Error — something went wrong on our end

503

Service Unavailable — database infrastructure error, try again later

Did this answer your question?