SMOC Public Contacts API — Integration Guide
Guide to the SMOC Public Contacts API — a read-only REST endpoint for listing contacts and aggregate counts for your company. Use it from custom integrations, sync jobs, or alongside the Zapier app.
Overview
The SMOC Public API lets third-party systems read contacts for a single company. It is hosted on Cloudflare Workers and scoped automatically to the company tied to your API key.
What it does today:
- List contacts for your company (up to 500 per request)
- Return aggregate counts of leads and customers
- Scope data automatically to the company tied to your API key
What it does not do:
- Create, update, or delete contacts
- Paginate with cursors or offsets (only a
limitcap) - Query across multiple companies with one key
This Zapier/compat contract is staying. The sole contacts endpoint for that contract is:
GET /api/company/mongocontact
Richer contact search is additive: POST /api/v2/contacts_search. Do not migrate Zapier off mongocontact.
For Console setup, authentication, and a function overview, start with the REST API connection guide.
Get your API key
All SMOC data integrations use the same Console token pattern as Zapier and MCP:
- Log in to SMOC Console.
- Go to Settings → Integrations → API (use Integrations → Zapier for Zapier-specific setup).
- Optionally name the key and set an expiry, then click Generate new API key.
- Copy the key immediately — it is shown once and cannot be retrieved later.
Generating a new key does not revoke existing keys. Issued keys are listed on the same page — revoke unused keys there when you need to rotate credentials.
Each key is bound to one company. The key carries an operatorId claim equal to that company's ID. The API uses this to scope all contact data — you cannot pass a different company ID in the request.
Base URLs
| Environment | Base URL |
|---|---|
| Production | https://api.smoc.ai |
Full endpoint example:
GET https://api.smoc.ai/api/company/mongocontact
Authentication
Send your API key in a custom HTTP header named token:
GET /api/company/mongocontact HTTP/1.1
Host: api.smoc.ai
token: <your-api-key>
Content-Type: application/json
The API verifies the key and reads the operatorId claim to determine which company's contacts to return. You do not send a company ID in the URL or query string.
Do not use:
Authorization: Bearer …— this header is not accepted by this endpoint (despite what the Console "API Access" page may currently show). Use thetokenheader in integrations until product support for Bearer is added.- Clerk secret keys (
sk_…) or publishable keys (pk_…) — these are rejected with401 Invalid token type.
Request
Method: GET only. Other methods (e.g. POST) return 404 Not Found.
Query parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
limit |
integer | No | 100 |
Max contacts to return. Must be 1–500. |
sortByField |
string | No | (none) | Sort contacts descending by this field. |
status |
string | No | (none) | Filter by contact status. status=1 is the standard lead poll, including positive message-flow smart leads. |
Allowed sortByField values:
| Value | Sorts by |
|---|---|
createdAt |
Contact creation date. When this sort is requested (and status is omitted or 1), recent late smart leads from the last 14 days are merged in and the page is re-sorted by max(createdAt, leadCapturedAt) so they appear without displacing newer web contacts. |
updatedAt |
Last update date |
lastConversationDate |
Last conversation date |
leadCapturedAt |
When the contact became a smart lead (falls back to updatedAt for historical rows) |
companyUsers.lastConversationDate |
Legacy alias for lastConversationDate (Zapier compatibility) |
Sort is always descending (newest/highest first). If omitted, MongoDB's natural order is used.
Response
Success (200 OK)
{
"data": [ /* array of contact objects */ ],
"leadsCount": 42,
"customerCount": 18
}
| Field | Type | Description |
|---|---|---|
data |
array | Contact records for your company |
leadsCount |
number | Contacts with status "1" or null |
customerCount |
number | Contacts with status "2" |
leadsCount and customerCount reflect all contacts for the company, not just the current page.
Contact object fields
Each item in data includes only the fields below (sensitive/internal fields are excluded):
| Field | Description |
|---|---|
id |
Zapier poll identity. Usually the Mongo _id. Late-converting smart leads (leadCapturedAt at least 1 hour after createdAt, and on or after 2026-09-11) use {mongoId}__sl so New Contact can fire. Use contactId for the stable Mongo id. |
contactId |
Stable Mongo _id. Does not change when id is rewritten for a late smart lead. |
linkedinUrl |
LinkedIn profile URL when present (top-level linkedinUrl or the first linkedinProfiles[].url). |
userId |
User identifier |
email |
Email address |
firstName |
First name |
lastName |
Last name |
msisdn |
Phone number |
company |
Company name (contact's employer, if captured) |
city, state, street, zip |
Address fields |
status |
Contact lifecycle status (see below). Positive message-flow smart leads use "1" like web-form leads. |
leadSentiment |
"positive" or "negative" when a message-flow reply was classified; omitted otherwise |
leadCapturedAt |
ISO-8601 time the contact became a positive smart lead (falls back to updatedAt when missing) |
tags |
Resolved contact tags { id, name, systemKind? }[] (includes Auto: Positive Lead / Auto: Negative Lead) |
brandId |
Brand identifier |
operatorId |
Company/operator identifier |
createdAt |
ISO-8601 creation timestamp |
updatedAt |
ISO-8601 last update timestamp |
lastConversationDate |
ISO-8601 date of last conversation |
acceptedCommunication |
Whether the contact accepted communication |
acceptedPrivacy |
Whether the contact accepted privacy terms |
inviterUser |
Who referred this contact (object) |
rewardFlows |
Flows where rewards were earned |
promosPresented |
Promotions shown to the contact |
promosRedeemed |
Promotions redeemed |
answeredSurveyQuestions |
Survey responses |
usersReferred |
Users this contact referred |
referralLinks |
Referral link details |
visitList |
Visit/session history (device, UTM, geo, etc.) |
textFields |
Custom text fields captured in flows |
Fields may be null or absent if not collected for that contact.
Contact status values
| Status | Meaning |
|---|---|
"1" |
Lead (includes positive message-flow smart leads) |
"2" |
Customer |
"3" |
Lost |
"4" |
Converted |
null |
Treated as Lead in counts |
Nested object shapes
inviterUser
{
"id": 123,
"firstName": "Jane",
"lastName": "Doe",
"email": "jane@example.com"
}
rewardFlows / promos
{ "id": "...", "title": "Summer promo" }
referralLinks
{
"key": "...",
"campaignId": 1,
"campaignName": "...",
"flowVariantId": 1,
"url": "https://...",
"share": true
}
visitList — includes browser, os, deviceType, country, region, city, UTM fields (utmSource, utmMedium, utmCampaign, etc.), referrer, landingPage, userAgent, ip.
answeredSurveyQuestions — includes question/answer text, translations, reward info, and timestamps.
textFields — custom flow fields: flowId, flowName, variantId, variantName, key, value.
Error responses
All errors return JSON with an error field. Some include a hint.
| HTTP status | Condition | Example body |
|---|---|---|
401 |
Missing token header |
{ "error": "Missing token header" } |
401 |
Invalid/revoked key, or sk_/pk_ key used |
{ "error": "Invalid or revoked token", "hint": "You can create a valid token from the Integration Dashboard." } |
403 |
Valid key but no operatorId claim |
{ "error": "Unauthorized" } |
422 |
limit > 500 |
{ "error": "limit must not exceed 500" } |
422 |
Invalid sortByField |
{ "error": "Invalid sortByField value" } |
422 |
Invalid status |
{ "error": "Invalid status value" } |
404 |
Wrong path or method | Not Found (plain text) |
Example requests
Basic — fetch up to 100 contacts:
curl -s \
-H "token: YOUR_API_KEY" \
"https://api.smoc.ai/api/company/mongocontact"
Fetch 25 contacts, sorted by last conversation:
curl -s \
-H "token: YOUR_API_KEY" \
"https://api.smoc.ai/api/company/mongocontact?limit=25&sortByField=lastConversationDate"
Fetch standard leads (web-form and positive message-flow smart leads):
curl -s \
-H "token: YOUR_API_KEY" \
"https://api.smoc.ai/api/company/mongocontact?status=1&sortByField=leadCapturedAt"
Example truncated response:
{
"data": [
{
"id": "665a1b2c3d4e5f6789012345",
"email": "alex@example.com",
"firstName": "Alex",
"lastName": "Smith",
"msisdn": "+4712345678",
"status": "2",
"operatorId": "10",
"createdAt": "2025-03-15T10:22:00.000Z",
"lastConversationDate": "2025-06-01T14:30:00.000Z",
"visitList": [
{
"deviceType": "mobile",
"browser": "Chrome",
"country": "NO",
"utmSource": "google"
}
]
}
],
"leadsCount": 120,
"customerCount": 45
}
Zapier integration
SMOC provides a Zapier app that uses this same endpoint. Typical flow:
- Get access via the Zapier invite link (linked from Console → Settings → Integrations → Zapier).
- Generate an API key in Console.
- In Zapier: My Apps → Custom Integrations → Add Connection and paste the key when prompted for a token.
- Create a Zap with trigger SMOC → New Contact.
The Zapier trigger polls this endpoint and treats returned contacts as new when they appear. New Contact keys on id. Late-converting smart leads (imported prospects that later get leadCapturedAt) now receive a stable {contactId}__sl id so the existing New Contact Zap can fire once. contactId remains the Mongo id for CRM mapping. This applies to every company; only captures on or after 2026-09-11 are rewritten (temporary until a dedicated New Smart Lead trigger exists). Prefer HubSpot Create or Update Contact on email to avoid duplicates if the prospect was already synced. See the Zapier eGuide for step-by-step setup.
Limitations and design notes
- Customer keys are read-only — mongocontact does not write. REST v2 mutating tools are super-admin only.
- No offset/cursor pagination — use
limit(max 500). To sync all contacts, sort consistently and track seen IDs client-side, or use Zapier's polling model. - Automatic scoping — the API key determines the company; there is no multi-tenant override parameter.
- Projection-limited fields — only the fields listed above are returned; internal database fields are stripped.
- Legacy compatibility — the endpoint path and
companyUsers.lastConversationDatesort alias exist for backward compatibility with the original API and Zapier app.
Related: MCP (AI clients)
The same API worker also exposes MCP at https://api.smoc.ai/mcp and REST v2 at POST /api/v2/{toolName} with richer contact tools (contacts_search, contacts_get, contacts_get_stats, etc.). See the MCP eGuide and the REST v2 reference.
For a product overview of all integration paths, see smoc.ai/integrations.
Quick reference
| Item | Value |
|---|---|
| Endpoint | GET /api/company/mongocontact |
| Auth header | token: <api-key> |
| Content type | application/json |
| Max page size | 500 |
| Default page size | 100 |
| Company scope | From API key (operatorId claim) |
| Key creation | Console → Settings → Integrations → API |
See also
- REST v2 API reference — every
POST /api/v2/{toolName}call - Connecting SMOC with the REST API
- Public Contacts API
- MCP for Claude, Cursor, and VS Code
Stay close to the shift in AI sales
Get product updates and perspective on proactive AI agents, multichannel orchestration, and conversion—without the noise.