We use necessary cookies to keep you signed in and remember your language. With your consent we also use analytics to understand traffic and improve the service. Privacy Policy

Essential cookies

Always on

Keep you signed in and remember your language and cookie preferences so the app works as expected.

Google Analytics helps us understand visits and improve the service.

Contentsquare manages its privacy settings separately. Privacy Policy

LucienOpen developer tools →

Developer docs

Place AI phone calls and collect their results from your own code or an AI agent. Two surfaces, one set of capabilities: a REST API and a remote MCP server. Calls draw from your account's credit balance.

Authentication

Create a key in Developers → API keys (shown once). Send it as a bearer token on every request. Keys carry scopes: calls:write, calls:read, campaigns:write, billing:read.

Authorization: Bearer cai_live_xxxxxxxxxxxxxxxxxxxxxxxx

Base URL: /api/v1 · OpenAPI: /api/v1/openapi.json

Quickstart — place a call

One request creates everything and dials. Poll the returned call until isComplete is true.

# 1. Place the call
curl -X POST https://app.asklucien.com/api/v1/calls \
  -H "Authorization: Bearer $LUCIEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "phone": "+33185094454",
    "language": "fr",
    "objective": "book a table for 2 tonight at 8pm",
    "collect": ["confirmation", "deposit required?"]
  }'
# → { "id": "call_…", "status": "dialing", "isComplete": false, ... }

# 2. Poll for the result
curl https://app.asklucien.com/api/v1/calls/call_… \
  -H "Authorization: Bearer $LUCIEN_API_KEY"
# → { "status": "completed", "outcome": "success",
#     "summary": "...", "collected": { "confirmation": "..." },
#     "priceUsd": 0.15, "isComplete": true }

Endpoints

Method & pathDescription
POST /callsPlace a single call
GET /callsList your calls (filter by requestId, status)
GET /calls/{id}Get a call's status + result
POST /calls/{id}/refreshForce-pull the latest result
POST /calls/{id}/cancelHang up a live call
GET /calls/{id}/transcriptTranscript (?translate=<lang>)
GET /calls/{id}/recordingStream the recording (audio/mpeg)
POST /campaignsStart a discovery campaign
GET /campaigns/{id}Campaign progress + ranked results
GET /balanceSpendable credit + per-call estimate

Discovery campaigns

Find businesses and call several of them for one objective. Calls are paced automatically; poll the campaign for the AI-ranked summary.

curl -X POST https://app.asklucien.com/api/v1/campaigns \
  -H "Authorization: Bearer $LUCIEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "query": "flower shops in Mykonos",
        "objective": "cheapest price for a dozen red roses",
        "maxTargets": 5 }'
# Then poll GET /campaigns/{id} → { "isComplete": true,
#   "headline": "…", "results": [ { "businessName": "…", "value": "4 €/rose" } ] }

Webhooks

Instead of polling, register an endpoint in Developers → Webhooks. We POST a signed JSON body on call.completed, call.failed and campaign.completed. Verify the X-Lucien-Signature header (HMAC-SHA256 of the raw body with your endpoint secret) and dedupe on X-Lucien-Delivery.

// Express receiver — verify the signature
import crypto from "node:crypto"

app.post("/hooks/lucien", express.raw({ type: "*/*" }), (req, res) => {
  const sig = req.header("X-Lucien-Signature") || ""
  const expected = "sha256=" + crypto
    .createHmac("sha256", process.env.WEBHOOK_SECRET)
    .update(req.body)            // the raw bytes
    .digest("hex")
  if (sig !== expected) return res.status(400).end()

  const { event, data } = JSON.parse(req.body.toString())
  // event: "call.completed" | "call.failed" | "campaign.completed"
  // data: the same shape as GET /calls/{id} or /campaigns/{id}
  res.status(200).end()
})

MCP server

Connect an AI client (Claude Desktop/Code, Cursor, …) to the remote MCP server. Same API key, same capabilities as tools: place_call, start_discovery_campaign, get_call, get_campaign, list_calls, get_transcript, cancel_call, get_balance.

{
  "mcpServers": {
    "lucien": {
      "url": "https://app.asklucien.com/api/mcp",
      "headers": { "Authorization": "Bearer cai_live_…" }
    }
  }
}

Errors

Errors return { "error": { "code", "message" } } with a matching HTTP status. Switch on code.

401unauthenticated — missing/invalid API key
402insufficient_credit — top up to place calls
403forbidden_scope — key lacks the required scope
404not_found
422validation_error — body/query failed the schema
429rate_limited
502dial_failed — both voice providers failed
503no_voice_provider

Create an API key to get started.