docs
/
AppEngine API

CRM

Leads, pipelines, campaigns, ads, tickets, reservations, signed documents and the AI assistant.

The largest domain module — 16 controllers under /crm/*. It spans lead management, marketing and advertising, support ticketing, appointments and e-signature.

Each section below links to its live specification: every endpoint with its parameters, responses and examples, generated from the running server. This page explains what the area does and why it is shaped that way — the part a generated document cannot tell you.

Leads

Leads are records with a lifecycle rather than a status field: qualify, disqualify, convert to a customer, assign an owner, schedule a follow-up. Converting is the one that crosses a boundary — it creates the customer record and links the two.

Leads — 23 endpoints →

Search (search on the leads list) matches name, email, phone, company and job title, and treats the text literally — regex characters are escaped, so ( no longer fails the query.

Pipelines

Stored as lead_pipeline records with ordered stages. Stages can be added, reordered or retargeted without touching the leads sitting in them. A pipeline can also redistribute its own unowned leads according to its routing rules, which is how a shared inbox of inbound leads gets divided without anyone assigning them by hand.

Won and lost are outcomes. A stage marked isWon / isLost (or named Won, Lost, Closed Won, Closed Lost) can be reached from any stage — the pipeline's allowSkipStages: false rule only governs open stages. Moving a lead into a won stage sets status: converted and closedAt; into a lost stage sets status: lost and closedAt (send lostReason on the same or a following update); moving it back to an open stage clears them and sets status: qualified. The forecast (won / wonCount, weighted open value by close month and owner) reads the same flags.

Pipelines — 10 endpoints →

Scoring and enrichment

Scoring and enrichment both run per-lead or in batch. Enrichment is asynchronous — start it, then poll for status. It is backed by the enrichment service (/enrichment/*), which fans out to multiple data providers, so the wait is real and the answer arrives later.

Importing

Leads arrive from Facebook lead forms, from contact lists, and in bulk. This is also where the LeadSearch extension delivers what it scrapes.

POST /crm/leads/import takes spreadsheet rows as parsed JSON — { rows: [{ "<column>": "<value>" }], pipelineId?, stageId? } — and recognises column names server-side, including HubSpot's export names (First Name, Last Name, Email, Phone Number, Company Name, Job Title, Lead Status, Lifecycle Stage, Amount, Contact owner, …). Unrecognised columns are kept in customFields. Each row goes through the same createLead path as a single lead (numbering, scoring, pipeline stage). An email that is already a lead, or repeats within the file, is skipped. At most 5,000 rows per call. The reply says what happened:

{ "total": 5, "created": 2, "skipped": 2, "failed": 1,
  "skippedRows": [{ "row": 3, "reason": "[email protected] is already a lead" }, { "row": 4, "reason": "empty row" }],
  "errors": [{ "row": 5, "error": "Invalid email format: \"not-an-email\"" }] }

Row numbers are spreadsheet rows (the header is row 1). Requires create permission on leads.

Forms

Public form capture — what a marketing site posts to, with no session. Two shapes are accepted: a classic form post, and JSON. Submissions become form_submission records; the definitions they are validated against are crm_form records.

The public read (GET /crm/form/:name, GET /client/forms/:name) returns only what a visitor needs to draw and send the form — its name, title, description, thank-you message, access and authentication mode, window and schema. The stored record's notification address, author and participants are not included.

A submission does not create a lead by itself; an automation on form_submission with the create_lead action does (see Automation).

Forms — 6 endpoints →

Tickets

Support ticketing with a distinction worth knowing before you write a client: replies are customer-visible, comments are internal. Both hang off the same ticket; only one of them is ever shown to the person who raised it.

Tickets are also addressable by email without a session, so a customer can follow their own ticket from a link rather than an account.

Rules a client can rely on:

  • A ticket must have a title — creating one without is a 400 A ticket needs a subject.
  • data.name is always an 8-character ticket number ([A-Z0-9]), minted by the server whatever the form sent; it is what [#NUMBER] reply threading matches.
  • Every ticket starts on the ticket workflow on creation — including staff-created ones through POST /crm/tickets/update — so its SLA (the workflow's stage deadlines) runs from the start. Setting the status moves the workflow to the matching stage; setting a resolved ticket back to open returns the workflow to its first stage.
  • A customer reading GET /repository/get/ticket/:id receives only a ticket they reported (by author or reportedByEmail); anyone else's answers 404.

Tickets — 19 endpoints →

Reservations and appointments

A public booking page needs only two calls: read the reservation_definition records, then generate the available slots. Everything after that — creating, updating, reminding — is authenticated.

Customers manage their own bookings by email, again without an account. The resources being booked are service_point records. Video meetings get their own token-issued room.

Reservations — 16 endpoints →

Signed documents

E-signature on signed_document records: send, remind, cancel, void. Documents can be listed by the record they are attached to — the contracts on a customer, the waivers on a booking — rather than only as a flat list.

The signer portal is public and token-addressed, because the person signing is usually not a user of the platform.

Documents — 13 endpoints →

Marketing campaigns

Campaigns across platforms, with per-campaign analytics and an aggregated view for a dashboard.

Marketing — 12 endpoints →

Audiences

Segments, custom audiences, targeting options, interests and locations. Two of these matter more than the rest: overlap between two segments and reach estimation are both computed before you spend money, not after.

Audiences — 14 endpoints →

The largest area in CRM: campaign management, control (launch, pause, resume, schedule, duplicate — individually or in bulk), cross-platform campaigns, templates, metrics, analytics, ad accounts, creatives, audiences, automation rules and report generation.

Backed by the Facebook Business SDK, Google Ads API and Twitter API v2.

Ad accounts and readiness

Before a campaign launches, the server checks each ad platform it targets: is it connected, does the token carry the ads permission, and is there a usable ad account. A launch that fails the check is refused up front with 409 and reason: "ads_not_ready" rather than failing on every platform.

GET/crm/marketing/campaign-manager/ads-readiness?campaign=&refresh=JWT
GET/crm/marketing/campaign-manager/ads-readiness/:campaignIdJWT
GET/crm/marketing/campaign-manager/ad-accounts?platform=&refresh=JWT
GET/crm/marketing/campaign-manager/ad-accounts/:platformJWT
POST/crm/marketing/campaign-manager/ad-accounts/defaultJWT

Readiness lists every issue per platform with the place that fixes it. ad-accounts returns the accounts the connected login can see, each marked usable or not with the reason — what the Studio's per-platform ad account pickers show. ad-accounts/default saves a connection's default account ({ platform, accountId }; accountId: null clears it), and only an account the platform reports usable is accepted.

A campaign launches from its own ad account override, else the connection's default. The platform's campaign id is kept per platform on the campaign (platformReferences); on Google, pause, delete and metrics go to the account the campaign was created in, not the org's default.

The Google integration uses google-ads-api 25 (Google Ads API v25). What that means for the payloads you send:

  • Campaign create always declares EU political advertising — the server sends DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING on every new campaign.
  • Bidding is set through the strategy's own field. Supported: MAXIMIZE_CLICKS (TARGET_SPEND), MAXIMIZE_CONVERSIONS, MAXIMIZE_CONVERSION_VALUE, MANUAL_CPC, ENHANCED_CPC, MANUAL_CPM, MANUAL_CPV. Retired strategies are mapped: TARGET_CPA → Maximize conversions with a target CPA, TARGET_ROAS → Maximize conversion value with a target ROAS, TARGET_CPM → Manual CPM. Anything else is refused.
  • Text ads are responsive search ads. Expanded text ads can no longer be created; a text ad needs at least 3 headlines and 2 descriptions (up to 15 and 4 are sent).
  • Responsive display ads need headlines and a final URL; images, square images (the landscape images are reused when none are given) and logos are uploaded as image assets in the same request. Video ads need a YouTube URL and a final URL; the video becomes a video asset.
  • Extensions are assets — sitelink, call, callout, structured snippet, price and app — created and linked to a campaign or ad group in one request. Location extensions cannot be created through the API: Google builds them from a linked Google Business Profile, so the call returns an error telling you to link the profile in Google Ads (Assets › Locations).
  • Shopping creates product Shopping ads only; Showcase Shopping ads were retired and are refused.
  • Customer Match uploads contacts through an offline user data job, in batches of 10,000. Emails are trimmed, lowercased (dots dropped before @gmail.com / @googlemail.com) and SHA-256 hashed; phones are normalised to E.164 (a 10-digit number is taken as +1) and hashed; an address match needs first name, last name and postal code (names hashed, country and postal code plain, country defaulting to US). If no contact has any of these the upload is refused. Google can take up to a day to match.
  • Similar audiences were retired; the similar-audience call now creates a lookalike list from the seed list.
  • Reports use the renamed GAQL fields — for example metrics.conversions_from_interactions_rate in place of metrics.conversion_rate.

Ads — 35 endpoints →

Auto-campaign

AI campaign generation. The flow is generate → preview → approve, so nothing is spent on unreviewed output. A preview can be regenerated per platform, varied, or checked for predicted performance before approval.

Auto-campaign — 11 endpoints →

AI assistant

Configurable assistants with tools, capabilities and triggers, stored as ai_assistant records. Execution is available buffered or streamed, and there is a test path that runs without side effects.

Voice assistants get their own setup and templates, with a Socket.IO gateway (ai-voice.gateway) carrying live audio.

CRM · AI — 15 endpoints →

Inbox and messaging

Conversations, messages and notifications, plus device registration for push — which is how Appmint Mobile receives notifications at all.

Templates can be rendered without sending, which is the difference between testing a template and mailing your customers a draft.

Inbox — 10 endpoints →

Communications

Unified call, SMS and voicemail history, with Twilio provisioning and recording transcription.

One distinction to keep straight: the SMS history endpoint reads what is stored here, while the Twilio SMS endpoint queries Twilio live. They can disagree, and when they do the live one is right about delivery and the stored one is right about what this platform knows.

Communications — 14 endpoints →

Customer activity

Visitor tracking that resolves anonymous sessions to known customers. identify links a visitorId to a customer and merges the anonymous timeline into the identified one — so the history from before they signed up is not lost. erase is the GDPR deletion path.

Related datatypes: web_visit, web_activity, activity.

Activity — 6 endpoints →

Promotions

Double opt-in: subscribe, then confirm by token. The subscriber-facing half is public, because it runs from links in email where there is no session to speak of.

Promotions — 11 endpoints →

Merchant customers

B2B receivables — invoices, outstanding balances, aging reports and dunning reminders, individually or in bulk.

Merchant accounts — 34 endpoints →

Social

Social profiles, posts and engagement across the connected platforms, kept in sync with social_activity records.

Social — 24 endpoints →

Also here

Benefits workflow and enrollments (5 endpoints), CRM-side events, SMS alerts, flexible per-customer data, workspace items, nearby-place lookup and invitations.

The full list for every area above is in the API directory, or search for a phrase at /documentation/search.