API Documentation
Full REST API reference to integrate your Norahelp AI phone agent and AI chat widget into your own applications.
- Getting Started
- Authentication
- Rate Limits
- Error Handling
- Phone Agents
- Agents
- Calls
- Availability
- Appointments
- Chat Widgets
- Send Message
- Get Conversations
- Widget Management
- Analytics
Getting Started
Welcome to the Norahelp API! This RESTful API allows you to integrate our AI phone agent and AI chat widget capabilities into your applications.
Base URL
https://norahelp.com/api
Quick Start
To get started with the API:
- Generate an API key from your Settings page
- Include your API key in the
Authorizationheader of all requests - Make requests to the endpoints documented below
Authentication
All API requests must be authenticated using Bearer token authentication. Include your API key in the Authorization header:
Authorization: Bearer YOUR_API_KEY
Example Request
curl -X POST https://norahelp.com/api/chat \ -H "Authorization: Bearer sk_your_api_key_here" \ -H "Content-Type: application/json" \ -d '{ "widget_key": "widget_xyz123", "message": "Hello", "user_code": "user_abc789" }'
Rate Limits
API requests are limited to 60 requests per minute per caller to ensure fair usage and protect against abuse.
X-RateLimit-Limit and X-RateLimit-Remaining headers so you can track your usage.
429 Too Many Requests response. Wait until the window resets before retrying.
Error Handling
The API uses standard HTTP status codes. All error responses include a JSON body with details:
| Status Code | Meaning |
|---|---|
200 |
Success - Request completed successfully |
400 |
Bad Request - Invalid parameters |
401 |
Unauthorized - Invalid or missing API key |
403 |
Forbidden - Plan limit reached |
404 |
Not Found - Resource doesn't exist |
429 |
Too Many Requests - Rate limit exceeded |
500 |
Server Error - Something went wrong on our end |
Error Response Example
{
"success": false,
"error": "Invalid API key",
"message": "The provided API key is invalid or expired"
}
Phone Agents
Phone agents are the core product — discover the agents on your account here first, you'll need an agent's uuid for every other endpoint below.
List every phone agent on your account.
Example Request
curl -X GET https://norahelp.com/api/agents \
-H "Authorization: Bearer YOUR_API_KEY"
Success Response (200 OK)
{
"success": true,
"agents": [
{
"uuid": "84f117e4-54ed-4d2b-b081-54996c5748f6",
"name": "Nora",
"phone_number": "+4966197423959",
"language": "de",
"call_mode": "both",
"timezone": "Europe/Berlin",
"appointment_source": "internal",
"is_active": true,
"created_at": "2026-08-28T09:37:10+00:00"
}
]
}
Get one agent's full detail, including its products/services (each with an optional per-product appointment duration, used by the product parameter on the availability and booking endpoints below).
Success Response (200 OK)
{
"success": true,
"agent": {
"uuid": "84f117e4-54ed-4d2b-b081-54996c5748f6",
"name": "Nora",
"phone_number": "+4966197423959",
"language": "de",
"timezone": "Europe/Berlin",
"is_active": true,
"default_appointment_duration": 30,
"products": [
{ "name": "Probefahrt", "price": null, "duration_minutes": 45 }
]
}
}
Calls
List and inspect calls handled by your phone agents, including the full transcript. Read-only — calls themselves are only ever created by an actual incoming phone call, never through the API.
Get a paginated list of calls across all your phone agents, newest first.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| agent | string | Optional | Phone agent UUID, limits results to that agent only |
| status | string | Optional | One of: in_progress, completed, missed, failed |
| from | date | Optional | Only calls on or after this date (YYYY-MM-DD) |
| to | date | Optional | Only calls on or before this date (YYYY-MM-DD) |
| limit | integer | Optional | Number of calls to return (default: 50, max: 100) |
| offset | integer | Optional | Pagination offset (default: 0) |
Example Request
curl -X GET https://norahelp.com/api/calls?status=completed&limit=10 \
-H "Authorization: Bearer YOUR_API_KEY"
Success Response (200 OK)
{
"success": true,
"calls": [
{
"id": "call_41",
"agent_uuid": "84f117e4-54ed-4d2b-b081-54996c5748f6",
"agent_name": "Nora",
"agent_phone_number": "+4966197423959",
"caller_number": "+491736309521",
"status": "completed",
"duration_seconds": 91,
"appointment_booked": true,
"started_at": "2026-09-01T14:24:14+00:00",
"ended_at": "2026-09-01T14:25:45+00:00",
"created_at": "2026-09-01T14:24:14+00:00"
}
],
"total": 41,
"has_more": true
}
Get full detail for a single call, including its transcript. {id} is the id value from the list endpoint above (with or without the call_ prefix).
Example Request
curl -X GET https://norahelp.com/api/calls/call_41 \
-H "Authorization: Bearer YOUR_API_KEY"
Success Response (200 OK)
{
"success": true,
"call": {
"id": "call_41",
"agent_uuid": "84f117e4-54ed-4d2b-b081-54996c5748f6",
"agent_name": "Nora",
"caller_number": "+491736309521",
"status": "completed",
"duration_seconds": 91,
"appointment_booked": true,
"transcript": [
{ "role": "assistant", "content": "..." },
{ "role": "user", "content": "..." }
],
"started_at": "2026-09-01T14:24:14+00:00",
"ended_at": "2026-09-01T14:25:45+00:00"
}
}
Error Response (404 Not Found)
{
"success": false,
"error": "Call not found"
}
Availability
Check free appointment slots for a given day — the exact same logic the phone AI uses (business hours, existing bookings, recurring blockers, and the agent's configured buffer between appointments all already applied), so what this returns is always really bookable.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| date | date | Required | Date to check (YYYY-MM-DD) |
| product | string | Optional | Exact product/service name from GET /api/agents/{uuid} — determines slot length, falls back to the agent's default duration otherwise |
Example Request
curl -X GET https://norahelp.com/api/availability/84f117e4-54ed-4d2b-b081-54996c5748f6?date=2026-09-22 \
-H "Authorization: Bearer YOUR_API_KEY"
Success Response (200 OK)
{
"success": true,
"agent_uuid": "84f117e4-54ed-4d2b-b081-54996c5748f6",
"date": "2026-09-22",
"duration_minutes": 30,
"available_slots": ["09:00", "09:30", "10:00", "..."]
}
Appointments
Full appointment lifecycle — list, view, book, reschedule and cancel — backed by the same booking engine the phone AI uses. A slot that's rejected here would be rejected on a real call, and vice versa, they can never disagree.
Paginated list, newest first.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| agent | string | Optional | Phone agent UUID, limits results to that agent only |
| status | string | Optional | One of: confirmed, completed, cancelled, callback |
| from / to | date | Optional | Filter by appointment date (YYYY-MM-DD) |
| limit / offset | integer | Optional | Pagination (default limit: 50, max: 100) |
Success Response (200 OK)
{
"success": true,
"appointments": [
{
"id": "appt_28",
"agent_uuid": "84f117e4-54ed-4d2b-b081-54996c5748f6",
"agent_name": "Nora",
"call_id": "call_41",
"caller_name": "Max Mustermann",
"caller_phone": "+491736309521",
"appointment_at": "2026-09-22T07:00:00+00:00",
"duration_minutes": 30,
"notes": "Probefahrt",
"status": "confirmed"
}
],
"total": 12,
"has_more": true
}
Get a single appointment's full detail.
Book a new appointment. Always re-checked against live availability server-side, even if you called GET /api/availability a moment ago — if someone else took the slot in between, this returns 409 instead of silently double-booking.
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| agent | string | Required | Phone agent UUID |
| caller_name | string | Required | Name the appointment is booked under |
| date / time | string | Required | YYYY-MM-DD and 24h HH:MM, in the agent's own timezone |
| product | string | Optional | Same as on the availability endpoint, determines slot length |
| caller_phone | string | Optional | Contact number for the appointment |
| notes | string | Optional | Short note on what the appointment is for |
Example Request
curl -X POST https://norahelp.com/api/appointments \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"agent": "84f117e4-...", "caller_name": "Max Mustermann", "date": "2026-09-22", "time": "09:00"}'
Success Response (201 Created)
{
"success": true,
"appointment": { "id": "appt_28", "status": "confirmed", "..." }
}
Error Response (409 Conflict — slot taken)
{
"success": false,
"error": "slot_no_longer_available"
}
Reschedule to a new date/time. Send date and time (same format as booking); the new slot goes through the same live availability check.
Example Request
curl -X PUT https://norahelp.com/api/appointments/appt_28 \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"date": "2026-09-22", "time": "10:30"}'
Cancel an appointment. Marks it cancelled (kept for your records, not deleted) and removes it from the owner's Google Calendar if it was synced there.
Example Request
curl -X DELETE https://norahelp.com/api/appointments/appt_28 \
-H "Authorization: Bearer YOUR_API_KEY"
Send Chat Message
Send a message to your AI chatbot and receive a response.
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| widget_key | string | Required | Your widget's unique identifier |
| message | string | Required | The user's message (max 2000 characters) |
| user_code | string | Required | Unique identifier for the user/session |
| context | object | Optional | Additional context (user info, page URL, etc.) |
Example Request
curl -X POST https://norahelp.com/api/chat \ -H "Authorization: Bearer sk_your_api_key" \ -H "Content-Type: application/json" \ -d '{ "widget_key": "widget_abc123", "message": "What are your business hours?", "user_code": "user_unique_id_123", "context": { "page_url": "https://example.com/contact", "user_name": "John Doe" } }'
Success Response (200 OK)
{
"success": true,
"message": "Our business hours are Monday to Friday, 9 AM to 6 PM EST. We're closed on weekends and major holidays. How can I assist you today?",
"conversation_id": "conv_xyz789",
"timestamp": "2024-01-15T10:30:00Z"
}
JavaScript Example
const response = await fetch('https://norahelp.com/api/chat', { method: 'POST', headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ widget_key: 'widget_abc123', message: 'Hello!', user_code: 'user_123' }) }); const data = await response.json(); console.log(data.message); // AI response
Python Example
import requests url = "https://norahelp.com/api/chat" headers = { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" } payload = { "widget_key": "widget_abc123", "message": "What services do you offer?", "user_code": "user_456" } response = requests.post(url, headers=headers, json=payload) data = response.json() print(data["message"])
Get Conversations
Retrieve conversation history for a specific widget.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| limit | integer | Optional | Number of conversations to return (default: 50, max: 100) |
| offset | integer | Optional | Pagination offset (default: 0) |
| user_code | string | Optional | Filter by specific user |
Example Request
curl -X GET https://norahelp.com/api/conversations/widget_abc123?limit=10 \
-H "Authorization: Bearer sk_your_api_key"
Success Response (200 OK)
{
"success": true,
"conversations": [
{
"id": "conv_123",
"user_code": "user_456",
"message": "What are your prices?",
"response": "Our pricing starts at $29/month...",
"timestamp": "2024-01-15T10:30:00Z"
}
],
"total": 145,
"has_more": true
}
Widget Management
Manage your chatbot widgets via API.
Get list of all your widgets.
Get details of a specific widget.
Update widget settings. Send only the fields you want to change.
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Optional | New display name for the widget |
| welcome_message | string | Optional | Greeting shown when a chat starts |
| is_active | boolean | Optional | Enable or disable the widget |
Example Request
curl -X PUT https://norahelp.com/api/widgets/widget_abc123 \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"welcome_message": "Hi there! How can I help?"}'
Analytics
Access detailed analytics and statistics.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
| from | date | Start date (YYYY-MM-DD) |
| to | date | End date (YYYY-MM-DD) |
Response Example
{
"success": true,
"from": "2026-07-11",
"to": "2026-08-10",
"total_conversations": 21,
"total_messages": 42,
"unique_users": 5
}