API RU
Early access. API keys are issued on request. How to get a key

Read campaigns, leads, stored conversations and events from your Meliora organization in your CRM or your own system. Version v1, early access.

Make your first request in 5 minutesAPI reference

Request
curl https://api.melioralab.io/v1/me \
  -H "Authorization: Bearer $MELIORA_API_KEY"
Response, shortened
{
  "object": "api_context",
  "organization": {
    "id": "2c8f4a61-7d3e-4b9a-8f21-6a0d5e9c3b17",
    "name": "Example"
  },
  "scopes": [
    "campaigns:read",
    "events:read",
    "leads:read",
    "messages:read"
  ],
  "api_version": "v1"
}

Prompt for your AI assistant

Paste this text into Claude, ChatGPT, Cursor or another assistant. It will read the API docs and follow our integration rules. The text contains no key.

Open as text

Show the prompt text
# AI agent prompt: integrating with the Meliora API

You are helping a developer connect to the Meliora public API. Meliora is a service for automated Telegram outreach and conversations for B2B. It has an organization, workspaces, campaigns (message sequences), leads (a contact's participation in a campaign), stored conversations and an event feed.

## Read the docs first

Before you write code or answer, read these files. They are more accurate than your memory:

1. https://docs.melioralab.io/en/llms.txt: the docs table of contents, with links to the Markdown of every page.
2. https://docs.melioralab.io/en/llms-full.txt: the full docs in one file.
3. https://docs.melioralab.io/en/openapi.json: the OpenAPI 3.1 spec, the only source of truth for routes, parameters and fields.

If you don't have network access, ask the user to send you the contents of these files.

## What the API can do

- Version v1, read-only. There is no write access: you can't add contacts or start or stop a sequence through the API. That is done in the Meliora app.
- Base URL: https://api.melioralab.io/v1
- Routes, all GET: /me, /workspaces, /campaigns, /campaigns/{id}, /leads, /leads/{id}, /leads/{id}/messages, /events.
- Responses are JSON. Timestamps are UTC ISO 8601 with milliseconds. Errors use application/problem+json with the fields status, code, param and request_id. Handle errors by status and code, not by message text.

## Key and security

- Send the key only in the header Authorization: Bearer <key>. Never put the key in the request URL.
- Read the key from the environment variable MELIORA_API_KEY. Don't ask the user to paste the key into the chat, and never print the key in replies, code, logs or commits.
- Call the API only from a server, never from a browser.
- The first step is always GET /v1/me: it returns the key's permissions (scopes), scope and limits. Check that the permissions cover the task before you write the rest of the code.

## Integration rules

- Lists are paginated with a cursor: repeat the request with cursor=next_cursor and the same filters while has_more is true. limit is up to 100, up to 200 for /events. A list cursor lives for 15 minutes.
- The /events feed has two event types: lead.first_message_sent and lead.replied. Save next_cursor from every response, even an empty one. Apply a page's events and save the new cursor in one transaction. Deduplicate events by event.id. When has_more is false, wait between one minute and one hour before polling again.
- First run of the feed: GET /v1/events?start=now returns a cursor. Then reconcile leads through /v1/leads, then read the feed from that cursor.
- A 410 cursor_expired or 400 cursor_mismatch response from the feed: record the gap, get a new cursor with start=now, reconcile campaigns and leads, and continue polling.
- 429 and 503 responses: retry the same request after Retry-After seconds with random jitter, and increase the delay on repeated 503s. An error doesn't move the cursor. Don't retry requests that got 401 in a loop.
- CRM mapping: the link key is fields.record_id on the lead record (/v1/leads, /v1/leads/{id}), and only when record_id_status is valid. Events don't carry record_id yet: match an event to a lead by data.lead.id. A Telegram username is not unique, so don't use it as a key.
- Only move CRM statuses forward: a lead's reply must not roll back to the "In progress" status.
- Message text is available only if the key has the messages:read permission and "Message text" is enabled.
- Not returned yet: delivery_state values failed and waiting_queue, automation_state value completed, reason_code values schedule_window and service_unavailable. In the reply event, automation_stopped is always null. The conversation archive and the feed may be incomplete: see meta.completeness and meta.coverage. The value unknown is normal, not an error.

## What not to do

- Don't invent routes, parameters, fields or values that are not in openapi.json. If something you need doesn't exist, say so and suggest a solution using the existing routes.
- Don't promise write access through the API: v1 doesn't have it.
- Check anything uncertain against the docs and link to the relevant page.

Docs: https://docs.melioralab.io/en/
Support: https://t.me/meliora_support

#What you can do

The API returns your organization's data as JSON, authenticated with an organization API key. Common use cases:

  • Sync replies to your CRM. The event feed tells you when a lead gets the first message and when they reply. The fields.record_id field on the lead links it to a CRM record.
  • Track campaign progress. Campaign and lead states, delivery state and the reason a lead is waiting, such as the sending window or the account's daily quota.
  • Pull conversations. Stored messages with a lead: sequence steps, manual messages from your managers, and replies.
  • Reconcile data. Lists of campaigns and leads, filtered by workspace, campaign, status and username.

#Endpoints

Every endpoint in v1 is read-only and uses the GET method.

EndpointReturnsPermission
GET /v1/meRetrieve API key detailsany
GET /v1/workspacesList workspacesany
GET /v1/campaignsList campaignscampaigns:read
GET /v1/campaigns/{id}Retrieve a campaigncampaigns:read
GET /v1/leadsList leadsleads:read
GET /v1/leads/{id}Retrieve a leadleads:read
GET /v1/leads/{id}/messagesList lead conversationmessages:read
GET /v1/eventsList eventsevents:read

#How the API works

  • Base URL: https://api.melioralab.io/v1.
  • Pass the key in the Authorization: Bearer mel_live_... header. The key belongs to your organization, not to a team member, so it keeps working if the person who created it leaves.
  • Responses are UTF-8 JSON. Field names use snake_case, IDs are UUIDs, and timestamps are ISO 8601 in UTC with a Z suffix.
  • A key sees only what its permissions and scope allow. To the key, an object outside its scope does not exist and returns 404.
  • Call the API from your server. Browser requests from third-party sites are not supported.

#Early access

The API is in early access. Keys are issued on request: contact Support, and we will enable API access for your organization and issue a key. Read access is available on the Pro plan and above.

Before you start:

  • Read-only. You can't import contacts or start or stop a sequence through the API yet. Do this in Meliora instead.
  • The conversation archive may be incomplete. The API returns what has been stored. meta.completeness tells you how complete it is.
  • The feed keeps events for 30 days. Poll it regularly. After a long outage, reconcile records as described in Polling events.
  • Some status values are not sent yet. See Lead and delivery states for details.

#Where to start

  1. Quickstart: make your first request in 5 minutes.
  2. Authentication and keys: permissions, scope, rotation and revocation.
  3. Polling events: a reliable polling loop for CRM integrations.
  4. API reference: every field, parameter and example response.
  5. AI agents and MCP: how to give these docs to Claude, ChatGPT, Cursor or Claude Code.

You can download the OpenAPI 3.1 specification: openapi.json. Import it into Postman, Insomnia or a client generator.