Public HTTP endpoints that power the AI Repair Estimate Assistant — a chat intake a shop embeds on its own site so a vehicle owner can turn a vague damage description into an estimator-ready repair intake.
Beta. This surface is gated by the
repair_estimatorentitlement and is intended for first-party / embedded use on a shop's own website. Unlike the rest of the SocialCRM API, these endpoints are public and unauthenticated — there is no API key. Access is scoped per shop by aslug, per visitor by an opaque sessiontoken, and per browser origin by the shop's configuredallowed_origins. Endpoints, request shapes, and limits may change while in beta.
How it differs from the rest of the API
| MCP / REST platform | Repair Estimator | |
|---|---|---|
| Auth | Authorization: Bearer sk_live_… API key |
None — public |
| Tenant scoping | API key → company | slug (shop) + token (session) |
| Cross-origin | Server-to-server | Browser embed, gated by allowed_origins (CORS) |
| Base path | /api/mcp-app |
/api/public/repair-estimator |
Base URL: https://socialcrm.com/api/public/repair-estimator
CORS & origins
These endpoints are called from a browser on the shop's website. Send an Origin header; it must match the shop's configured allowed_origins (or a first-party SocialCRM origin). When the origin is allowed, the response echoes it in Access-Control-Allow-Origin. Each route also answers a OPTIONS preflight. A disallowed cross-origin request is rejected as 404. Non-browser requests (no Origin) are not blocked by CORS and are still subject to per-IP rate limits and per-tenant caps.
Typical flow
GET /config/{slug}— load branding for the widget.POST /sessions— start a session, receive atoken.POST /sessions/{token}/messages— one call per chat turn.POST /sessions/{token}/contact— capture the lead once the owner consents.GET /sessions/{token}— rehydrate an in-progress session (e.g. page reload).
GET /config/{slug}
Public, cacheable branding for a live estimator. Returns 404 if the slug is unknown or the estimator is not published.
Rate limit: 60 requests / minute / IP. Response is cacheable (Cache-Control: public, max-age=60).
curl https://socialcrm.com/api/public/repair-estimator/config/joes-auto-body{
"data": {
"slug": "joes-auto-body",
"displayName": "Joe's Auto Body",
"welcomeMessage": "Tell me what happened and I'll help you get a head start on an estimate.",
"disclaimerText": "This is a preliminary intake, not a quote. Final pricing requires an in-person inspection.",
"theme": { "accent": "#047857" },
"locale": "en-US",
"units": "imperial"
}
}POST /sessions
Start an intake session. The slug identifies the shop; source is optional caller-supplied context (UTM, page URL, etc.).
Gated by the shop's repair_estimator entitlement and monthly intake cap. Rate limit: 5 requests / hour / IP.
curl -X POST https://socialcrm.com/api/public/repair-estimator/sessions \
-H "Content-Type: application/json" \
-H "Origin: https://joesautobody.com" \
-d '{ "slug": "joes-auto-body", "source": { "page": "/estimate" } }'{
"data": {
"token": "rin_8sQ2…",
"expiresAt": "2026-08-01T16:00:00.000Z"
}
}The token is the credential for every subsequent call on this session. Treat it as a bearer secret for that visitor.
GET /sessions/{token}
Rehydrate a session — its status, captured vehicle data, safety flag, the shop's display config, and recent messages. Returns 404 once the session has expired.
Rate limit: 30 requests / minute / IP.
curl https://socialcrm.com/api/public/repair-estimator/sessions/rin_8sQ2…{
"data": {
"session": { "status": "active", "vehicle": {}, "safetyFlag": false, "expiresAt": "2026-08-01T16:00:00.000Z" },
"config": { "slug": "joes-auto-body", "displayName": "Joe's Auto Body", "welcomeMessage": "…", "disclaimerText": "…", "theme": {} },
"messages": [
{ "id": "…", "role": "assistant", "content": "What year, make, and model is the vehicle?", "metadata": {}, "createdAt": "…" }
]
}
}POST /sessions/{token}/messages
Send one chat turn. Returns the assistant's structured turn envelope plus updated session counters.
Rate limit: 10 requests / minute / IP. Per-session cap: 80 messages. Also subject to the shop's monthly turn budget.
curl -X POST https://socialcrm.com/api/public/repair-estimator/sessions/rin_8sQ2…/messages \
-H "Content-Type: application/json" \
-H "Origin: https://joesautobody.com" \
-d '{ "message": "2019 Honda Civic, someone rear-ended me and the bumper is cracked." }'{
"data": {
"turn": {
"reply": "Got it — a 2019 Civic with rear impact. Is the vehicle drivable, and did any warning lights come on?",
"phase": "damage",
"intake_draft": { "…": "partial RepairIntake v1" },
"intake_complete": false,
"safety_concern": null,
"followups": ["drivability", "warning lights"]
},
"session": { "status": "active", "messageCount": 4, "safetyFlag": false }
}
}The assistant never returns prices, part numbers, labor hours, or insurance determinations; those are stripped by an output policy before the reply is returned or stored.
POST /sessions/{token}/contact
Capture the lead once the owner consents to send their intake to the shop. Creates or updates a CRM contact, marks the session submitted, and notifies configured staff.
consent must be true. honeypot must be empty (a filled honeypot returns a silent success and is discarded). Rate limit: 3 requests / hour / IP.
curl -X POST https://socialcrm.com/api/public/repair-estimator/sessions/rin_8sQ2…/contact \
-H "Content-Type: application/json" \
-H "Origin: https://joesautobody.com" \
-d '{ "name": "Alex Rivera", "email": "alex@example.com", "phone": "555-123-4567", "consent": true }'{
"data": { "success": true, "ignored": false, "crmContactId": "…" }
}Errors
| Status | Meaning |
|---|---|
400 |
Invalid or missing request body |
402 |
Estimator not entitled for this shop, or monthly cap reached |
404 |
Unknown/unpublished slug, expired or unknown token, or disallowed origin |
429 |
Per-IP rate limit or per-session message cap exceeded |
502 |
Upstream AI provider error or timeout |
Rate-limited responses include standard RateLimit-* headers and, where applicable, retryAfter (seconds) in the body.