English
Support
Norahelp
Login Get Started
Developers

API Documentation

Full REST API reference to integrate your Norahelp AI phone agent and AI chat widget into your own applications.

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:

  1. Generate an API key from your Settings page
  2. Include your API key in the Authorization header of all requests
  3. Make requests to the endpoints documented below
Note: API access is available on plans with API access enabled. Upgrade now

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"
  }'
Security Warning: Never expose your API keys in client-side code. Always make API calls from your server.

Rate Limits

API requests are limited to 60 requests per minute per caller to ensure fair usage and protect against abuse.

Rate Limit Headers: Every response includes X-RateLimit-Limit and X-RateLimit-Remaining headers so you can track your usage.
Exceeding the limit: Requests beyond the limit receive a 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.

GET /api/agents

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 /api/agents/{uuid}

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 /api/calls

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 /api/calls/{id}

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.

GET /api/availability/{agent_uuid}

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.

GET /api/appointments

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 /api/appointments/{id}

Get a single appointment's full detail.

POST /api/appointments

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"
}
PUT /api/appointments/{id}

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"}'
DELETE /api/appointments/{id}

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.

POST /api/chat

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.

GET /api/conversations/{widget_key}

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 /api/widgets

Get list of all your widgets.

GET /api/widgets/{widget_key}

Get details of a specific widget.

PUT /api/widgets/{widget_key}

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.

GET /api/analytics/{widget_key}

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
}