Leads

Sales leads CRUD plus activities (followups), dedicated stage/assignee routes, and statuses. Lead payloads include assigned_to (email) plus assignee: { email, name }.

Quickstart

Base URL (canonical)

https://api.strackerapp.com/v1/

Same gateway also answers under /api/v1 on strackerapp.com. Prefer the api. subdomain. Do not use api.stracker.io (not wired; returns 403).

Environments (keep separate)

EnvBaseKeys
Productionhttps://api.strackerapp.com/v1sk_prod_… only
Local smokehttp://127.0.0.1:8888/api/v1sk_dev_… only

Never mix prod keys with local, or local keys with prod.

Auth (all endpoints)

Org-scoped Bearer API key. Agent keys act as the agent with reports_to ACL inheritance.

Authorization: Bearer sk_REPLACE
Content-Type: application/json

# Optional alternate header:
# X-Stracker-Api-Key: sk_REPLACE

Response envelope

{
  "success": true,
  "data":   { /* endpoint-specific payload */ }
}

Errors

Failed responses always have success: false and an error object with a stable code and a human-readable message:

{
  "success": false,
  "error": {
    "code":    "VALIDATION_ERROR",
    "message": "company_name is required"
  }
}
HTTP statusWhenWhat to do
400Validation failed (missing required fields, bad enum, migration not applied for company/contact notes, assignee not in org, slot unavailable).Read error.message; fix the payload.
401Missing or invalid Authorization / X-Stracker-Api-Key.Check the API key; confirm the header is present.
403Key is valid but lacks permission (e.g. non-admin calling agent admin endpoints), or org scope mismatch.Use an org-admin key, or confirm the resource belongs to the key's org.
404Resource not found or not visible to this org.Verify the id and org scoping.
500Unexpected server error.Retry with backoff; report if persistent.

Leads

Endpoints at a glance

ActionMethod + PathSummary
List leadsGET /leadsList sales leads in the org.
Create a leadPOST /leadsCreate a sales lead. Provide company_name and/or first_name/last_name. Optional note_id for UI-style auto-save of the actor’s own Text fo…
Get a leadGET /leads/{id}Fetch a single sales lead including assignee join.
Update a leadPATCH/PUT /leads/{id}Update lead fields. deal_stage_id syncs denormalized status to the stage name (same as UI). assigned_to must be an active org member emai…
List lead statuses / stagesGET /leads/statusesList deal stages available for leads.
Set lead stagePOST/PATCH /leads/{id}/stageMove a lead to a deal stage. Body: {"deal_stage_id": N}. Equivalent to PATCH lead with deal_stage_id.
Set lead assigneePOST/PATCH /leads/{id}/assigneeAssign a lead to an org member. Accepts assigned_to (email), user_id, or org_user_id. Pass assigned_to: null to unassign. Rejects emails …
List lead activitiesGET /leads/{id}/activitiesActivity timeline (followups). Filter: all|pending|completed|upcoming|past.
Create lead activityPOST /leads/{id}/activitiesCreate Call/Text/Meeting/Email/…. Optional deal_stage_id moves the stage.
Get lead activityGET /leads/{id}/activities/{activityId}Fetch a single activity.
Update lead activityPATCH/PUT /leads/{id}/activities/{activityId}Update notes/date/outcome, or set action=complete|uncomplete|reschedule|delete. Reschedule bumps event_sequence and does not send ICS.
Delete lead activityDELETE /leads/{id}/activities/{activityId}Same as action=delete. Does not send a calendar cancel email.

GET /leads

List sales leads in the org.

Query parameters

FieldTypeRequiredDescription
q string no Free-text search
status string no Status / stage name filter
deal_stage_id integer no Filter by deal stage id
assigned_to string no Assignee email
limit integer no Page size Default: 50.
offset integer no Offset

Request example

curl -sS "https://api.strackerapp.com/v1/leads?limit=5" \
  -H "Authorization: Bearer sk_REPLACE"

Response 200 OK

{
  "success": true,
  "data": {
    "leads": [
      {
        "id": 1,
        "company_name": "Acme",
        "email": "[email protected]",
        "deal_stage_id": 2,
        "assigned_to": "[email protected]",
        "assignee": { "email": "[email protected]", "name": "Alex Rep" }
      }
    ],
    "pagination": { "limit": 5, "offset": 0 }
  }
}

POST /leads

Create a sales lead. Provide company_name and/or first_name/last_name. Optional note_id for UI-style auto-save of the actor’s own Text followup.

Body parameters

FieldTypeRequiredDescription
company_name string no Company name
first_name string no Contact first name
last_name string no Contact last name
email string no Email
phone string no Phone
website string no Website
channel_id integer no Lead channel id
deal_stage_id integer no Initial stage
assigned_to string no Org-member email
notes string no Initial notes
company_id integer no Link to CRM company
note_id integer no Optional Text followup auto-save id

Request example

curl -sS https://api.strackerapp.com/v1/leads \
  -H "Authorization: Bearer sk_REPLACE" \
  -H "Content-Type: application/json" \
  -d '{"company_name":"Acme","email":"[email protected]","deal_stage_id":1}'

Response 201 Created

{
  "success": true,
  "data": {
    "lead": { "id": 2, "company_name": "Acme", "email": "[email protected]", "deal_stage_id": 1 }
  }
}

GET /leads/{id}

Fetch a single sales lead including assignee join.

Path parameters

FieldTypeRequiredDescription
id integer yes Lead id

Request example

curl -sS https://api.strackerapp.com/v1/leads/1 \
  -H "Authorization: Bearer sk_REPLACE"

Response 200 OK

{
  "success": true,
  "data": {
    "lead": {
      "id": 1,
      "company_name": "Acme",
      "assigned_to": "[email protected]",
      "assignee": { "email": "[email protected]", "name": "Alex Rep" },
      "deal_stage_id": 2
    }
  }
}

PATCH PUT /leads/{id}

Update lead fields. deal_stage_id syncs denormalized status to the stage name (same as UI). assigned_to must be an active org member email (or null to unassign).

Path parameters

FieldTypeRequiredDescription
id integer yes Lead id

Body parameters

FieldTypeRequiredDescription
company_name string no Company name
first_name string no First name
last_name string no Last name
email string no Email
phone string no Phone
deal_stage_id integer no Move stage
assigned_to string no Assignee email or null
notes string no Notes
status string no Status string (prefer deal_stage_id)

Request example

curl -sS -X PATCH https://api.strackerapp.com/v1/leads/1 \
  -H "Authorization: Bearer sk_REPLACE" \
  -H "Content-Type: application/json" \
  -d '{"deal_stage_id":2,"assigned_to":"[email protected]"}'

Response 200 OK

{
  "success": true,
  "data": {
    "lead": { "id": 1, "deal_stage_id": 2, "assigned_to": "[email protected]" }
  }
}

GET /leads/statuses

List deal stages available for leads.

Request example

curl -sS https://api.strackerapp.com/v1/leads/statuses \
  -H "Authorization: Bearer sk_REPLACE"

Response 200 OK

{
  "success": true,
  "data": {
    "statuses": [
      { "id": 1, "name": "New" },
      { "id": 2, "name": "Qualified" }
    ]
  }
}

POST PATCH /leads/{id}/stage

Move a lead to a deal stage. Body: {"deal_stage_id": N}. Equivalent to PATCH lead with deal_stage_id.

Path parameters

FieldTypeRequiredDescription
id integer yes Lead id

Body parameters

FieldTypeRequiredDescription
deal_stage_id integer yes Target stage id

Request example

curl -sS -X POST https://api.strackerapp.com/v1/leads/1/stage \
  -H "Authorization: Bearer sk_REPLACE" \
  -H "Content-Type: application/json" \
  -d '{"deal_stage_id":1}'

Response 200 OK

{
  "success": true,
  "data": {
    "lead": { "id": 1, "deal_stage_id": 1, "status": "New" }
  }
}

POST PATCH /leads/{id}/assignee

Assign a lead to an org member. Accepts assigned_to (email), user_id, or org_user_id. Pass assigned_to: null to unassign. Rejects emails that are not active org_users.

Path parameters

FieldTypeRequiredDescription
id integer yes Lead id

Body parameters

FieldTypeRequiredDescription
assigned_to string no rep email; null to unassign
user_id integer no users.id
org_user_id integer no org_users.id

Request example

curl -sS -X POST https://api.strackerapp.com/v1/leads/1/assignee \
  -H "Authorization: Bearer sk_REPLACE" \
  -H "Content-Type: application/json" \
  -d '{"assigned_to":"[email protected]"}'

Response 200 OK

{
  "success": true,
  "data": {
    "lead": { "id": 1, "assigned_to": "[email protected]", "assignee": { "email": "[email protected]", "name": "Alex Rep" } }
  }
}

GET /leads/{id}/activities

Activity timeline (followups). Filter: all|pending|completed|upcoming|past.

Path parameters

FieldTypeRequiredDescription
id integer yes Lead id

Query parameters

FieldTypeRequiredDescription
filter string no all|pending|completed|upcoming|past
followup_type string no Text|Call|Meeting|Email|…
limit integer no Page size Default: 50.
offset integer no Offset

Request example

curl -sS "https://api.strackerapp.com/v1/leads/1/activities?limit=10" \
  -H "Authorization: Bearer sk_REPLACE"

Response 200 OK

{
  "success": true,
  "data": {
    "activities": [
      { "id": 55, "followup_type": "Text", "notes": "pinged", "completed": 0 }
    ]
  }
}

POST /leads/{id}/activities

Create Call/Text/Meeting/Email/…. Optional deal_stage_id moves the stage.

Path parameters

FieldTypeRequiredDescription
id integer yes Lead id

Body parameters

FieldTypeRequiredDescription
followup_type string yes Text|Call|Meeting|Email|…
notes string no Notes
followup_date string no YYYY-MM-DD HH:MM:SS
call_outcome string no e.g. connected
call_duration_minutes integer no Call length
meeting_type string no discovery_call|demo|follow_up_call|in_person
duration_minutes integer no Meeting duration
deal_stage_id integer no Optional stage move

Request example

curl -sS https://api.strackerapp.com/v1/leads/1/activities \
  -H "Authorization: Bearer sk_REPLACE" \
  -H "Content-Type: application/json" \
  -d '{"followup_type":"Text","notes":"smoke activity note"}'

Response 201 Created

{
  "success": true,
  "data": {
    "activity": { "id": 56, "followup_type": "Text", "notes": "smoke activity note" }
  }
}

GET /leads/{id}/activities/{activityId}

Fetch a single activity.

Path parameters

FieldTypeRequiredDescription
id integer yes Lead id
activityId integer yes Activity (followup) id

Request example

curl -sS https://api.strackerapp.com/v1/leads/1/activities/55 \
  -H "Authorization: Bearer sk_REPLACE"

Response 200 OK

{
  "success": true,
  "data": {
    "activity": { "id": 55, "followup_type": "Call", "call_outcome": "connected", "notes": "spoke 5m" }
  }
}

PATCH PUT /leads/{id}/activities/{activityId}

Update notes/date/outcome, or set action=complete|uncomplete|reschedule|delete. Reschedule bumps event_sequence and does not send ICS.

Path parameters

FieldTypeRequiredDescription
id integer yes Lead id
activityId integer yes Activity id

Body parameters

FieldTypeRequiredDescription
notes string no Notes
followup_date string no YYYY-MM-DD HH:MM:SS
call_outcome string no Call outcome
action string no complete|uncomplete|reschedule|delete

Request example

curl -sS -X PATCH https://api.strackerapp.com/v1/leads/1/activities/55 \
  -H "Authorization: Bearer sk_REPLACE" \
  -H "Content-Type: application/json" \
  -d '{"action":"reschedule","followup_date":"2026-09-25 15:00:00"}'

Response 200 OK

{
  "success": true,
  "data": {
    "activity": { "id": 55, "followup_date": "2026-09-25 15:00:00", "event_sequence": 2 }
  }
}

DELETE /leads/{id}/activities/{activityId}

Same as action=delete. Does not send a calendar cancel email.

Path parameters

FieldTypeRequiredDescription
id integer yes Lead id
activityId integer yes Activity id

Request example

curl -sS -X DELETE https://api.strackerapp.com/v1/leads/1/activities/55 \
  -H "Authorization: Bearer sk_REPLACE"

Response 200 OK

{
  "success": true,
  "data": { "deleted": true }
}