Mycel REST API
A small, opinionated REST surface for partners that don't speak MCP. Use this when a CRM, partner site, or back-office tool needs to read your offers or push leads programmatically.
Base URL
https://app.mycell.pro/api/v1
Authentication
All requests except GET /api/v1 require a Bearer token. Generate one in Settings → API keys. The full token is shown once — store it securely.
Authorization: Bearer myk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Each key has a list of scopes:
read:offers— list and read your offersread:leads— read leads created against your offerswrite:leads— create leads and drive the conversation flow used by ChatGPT Appsadmin— implies all of the above
Rate limits
100 requests / minute per API key. Limit headroom is returned in X-RateLimit-Remaining. Exceeding the limit returns 429 Too Many Requests with Retry-After: 60.
/api/v1Service descriptor. No auth required. Use it to discover endpoints, scopes and rate limits.
curl https://app.mycell.pro/api/v1
/api/v1/offersscope: read:offersList your tenant's offers. Supports filtering and pagination via offset.
Query parameters
| Name | Type | Description |
|---|---|---|
| category | string | Filter by category (e.g. real_estate, b2b_saas). |
| country | string | ISO 2-letter country code. |
| city | string | Case-insensitive substring match on city. |
| search | string | Substring match on title or description. |
| limit | number | Default 20, max 100. |
| offset | number | Default 0. |
| min_score | number | Minimum passport score (0-100). |
Example
curl -H "Authorization: Bearer $MYCEL_KEY" \ "https://app.mycell.pro/api/v1/offers?country=AE&limit=5"
/api/v1/offers/{slug}scope: read:offers (private only)Single offer by slug. Returns the raw row plus a structured manifest with DNA, hooks, FAQ and passport score — the same shape AI agents consume from /o/{slug}/manifest.json.
Public, active offers are readable without auth. Private/draft offers require an API key for the owning tenant.
curl https://app.mycell.pro/api/v1/offers/dubai-marina-2br
/api/v1/leadsscope: write:leadsPush a lead. Requires explicit user consent — you must collect it before calling. Idempotent on (tenant, offer_id, email_hash) — re-submitting the same email returns the original lead with duplicate: true.
Body
{
"offer_id": "uuid (optional)",
"name": "string (optional)",
"email": "string (optional)",
"phone": "string (optional)",
"whatsapp": "string (optional)",
"message": "string (optional)",
"source": "string (optional, default: 'api')",
"consent": true,
"metadata": { "your_ref": "..." }
}At least one of email, phone or whatsapp is required. consent must be true.
Example
curl -X POST https://app.mycell.pro/api/v1/leads \
-H "Authorization: Bearer $MYCEL_KEY" \
-H "Content-Type: application/json" \
-d '{
"offer_id": "8fde…",
"name": "Anna B.",
"email": "anna@example.com",
"message": "Looking for 2br with sea view, March move-in",
"consent": true
}'Response (201)
{ "data": { "id": "...", "status": "new", ... }, "duplicate": false }/api/v1/leads/{id}scope: read:leadsRead a lead you previously created. Useful for polling status as Mycel's AI worker qualifies the lead and updates score and qualification_score.
curl -H "Authorization: Bearer $MYCEL_KEY" https://app.mycell.pro/api/v1/leads/<uuid>
ChatGPT App Flow
For ChatGPT Apps / Actions, the recommended flow is: start conversation → send messages → request consent → create lead → optionally book. The same API key model is used; no extra auth layer is required.
/api/v1/conversationsscope: write:leadsStart an AI-native buyer conversation for an offer or existing lead. Use external_thread_id to make repeated calls idempotent from the same ChatGPT thread.
Body
{
"offer_id": "uuid (optional)",
"offer_slug": "string (optional)",
"lead_id": "uuid (optional)",
"source": "chatgpt-app",
"ai_surface": "chatgpt",
"external_thread_id": "thread_123 (optional)",
"first_message": "I need a 2BR in Marina under 3M AED",
"intent_passport": { "budget": "3M AED", "purpose": "buy" }
}/api/v1/conversations/{id}scope: read:leads or write:leadsRead the full conversation state: workflow status, messages, linked lead, handoffs, and canonical offer links.
/api/v1/conversations/{id}/messagesscope: write:leadsAppend a message to the conversation and update the running summary. You can pass a partial intent_passport to keep structured qualification data in sync.
{
"role": "buyer",
"content": "Need sea view and move-in by September",
"intent_passport": { "timeline": "September", "must_haves": ["sea view"] }
}/api/v1/conversations/{id}/consentscope: write:leadsMove the conversation into contact-consent stage and store the exact wording shown to the user.
/api/v1/conversations/{id}/leadscope: write:leadsConvert a consented conversation into a lead. Transcript and structured intent are copied into the lead record.
/api/v1/conversations/{id}/bookscope: write:leadsCreate a meeting handoff and return a prefilled booking URL for the attached offer.
Errors
All errors return a JSON body with an error field and an appropriate HTTP status.
| Name | Type | Description |
|---|---|---|
| 400 | invalid request | Malformed JSON or invalid id. |
| 401 | invalid_token / missing_token | API key missing, malformed, or revoked. |
| 403 | insufficient_scope | Key exists but lacks the required scope. |
| 404 | not_found | Resource does not exist or is not yours. |
| 422 | validation_failed | Required field missing (e.g. consent). |
| 429 | rate_limited | More than 100 req/min on this key. |
| 500 | server_error | Unexpected server error — please retry with backoff. |
Related surfaces
- MCP server — for AI agents (ChatGPT, Claude, Cursor):
/.well-known/mcp.json - Public manifest feed — for crawlers:
/feed/offers.json,/registry.json - Embeddable widget — for partner sites:
/settings/widgets