> ## Documentation Index
> Fetch the complete documentation index at: https://docs.meetecho.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Sign up, create an agent, and send your first voice notification in five steps.

## Prerequisites

You only need an HTTP client (curl, Postman, your language of choice). No SDK required — Echo is a plain REST API.

***

## Step 1 — Create your account

Sign up to get your business, default project, and API key in one request.

```bash theme={null}
curl -X POST https://api.meetecho.ai/v1/auth/signup \
  -H "Content-Type: application/json" \
  -d '{
    "email": "you@yourcompany.com",
    "password": "YourPassword123!",
    "first_name": "Jane",
    "last_name": "Doe",
    "business_name": "Acme Inc",
    "business_summary": "A SaaS platform for project management",
    "industry": "Software"
  }'
```

```json Response theme={null}
{
  "access_token": "eyJhbGci...",
  "refresh_token": "eyJhbGci...",
  "user": { "id": "...", "email": "you@yourcompany.com" },
  "business": { "id": "...", "name": "Acme Inc" },
  "default_project": {
    "id": "...",
    "name": "default",
    "api_key": "echo_6f437a610fbb..."
  }
}
```

<Warning>
  **Save your `api_key` immediately.** Echo stores only a hashed version. If you lose it, you'll need to generate a new one — it cannot be retrieved.
</Warning>

Pass the API key in the `x-api-key` header on every subsequent request:

```bash theme={null}
-H "x-api-key: echo_6f437a610fbb..."
```

The `business_summary` and `industry` fields give your agents automatic context — Echo uses them to fill `{{business_name}}`, `{{business_summary}}`, and `{{industry}}` in your prompts automatically.

***

## Step 2 — Create an agent

An Agent is a reusable voice persona. You define it once and trigger it for any customer at notification time.

```bash theme={null}
curl -X POST https://api.meetecho.ai/v1/agents \
  -H "x-api-key: echo_6f437a610fbb..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Appointment Reminder",
    "system_prompt": "You are a friendly assistant calling {{recipient_first_name}} on behalf of {{business_name}}. Start the call by saying: \"Hi, is this {{recipient_first_name}}? Great — I'\''m calling from {{business_name}} to confirm your appointment on {{appointment_time}} with {{doctor_name}}. Does that time still work for you?\" If they need to reschedule, collect a preferred time and end the call warmly. Do not discuss anything else.",
    "output_schema": {
      "type": "object",
      "required": ["confirmed"],
      "properties": {
        "confirmed": {
          "type": "boolean",
          "description": "Whether the patient confirmed the appointment"
        },
        "reschedule_request": {
          "type": "string",
          "description": "Preferred reschedule time if they want to change it"
        }
      }
    }
  }'
```

```json Response theme={null}
{
  "id": "ddb8be3b-a426-4122-b877-a0cba363c89d",
  "name": "Appointment Reminder",
  "status": "active",
  "created_at": "2026-03-18T17:43:46.714Z"
}
```

Save the `id` — you'll pass it as `agent_id` when triggering notifications.

`output_schema` is optional. When provided, Echo extracts structured data from the call transcript and stores it in `notification.call_result`, then includes it in the webhook payload.

***

## Step 3 — Add a customer

Customers are scoped to your project. Register the person you want to call before sending a notification.

```bash theme={null}
curl -X POST https://api.meetecho.ai/v1/customers \
  -H "x-api-key: echo_6f437a610fbb..." \
  -H "Content-Type: application/json" \
  -d '{
    "external_id": "user_12345",
    "first_name": "John",
    "last_name": "Smith",
    "phone": "+14155552671"
  }'
```

```json Response theme={null}
{
  "id": "8cc6199f-9466-46f2-9db7-936f3c2c1c0b",
  "project_id": "...",
  "external_id": "user_12345",
  "first_name": "John",
  "last_name": "Smith",
  "phones": [
    {
      "value": "+14155552671",
      "is_primary": true,
      "status": "active"
    }
  ]
}
```

<Tip>
  `external_id` is your own system's identifier. Use it to look up customers without storing Echo's UUIDs in your database. Phone numbers must be in E.164 format (`+[country code][number]`).
</Tip>

***

## Step 4 — Send a notification

With an agent and customer in place, trigger the call. Pass your custom variables in `variables` to fill any `{{placeholder}}` tokens in the agent's prompt.

```bash theme={null}
curl -X POST https://api.meetecho.ai/v1/notifications \
  -H "x-api-key: echo_6f437a610fbb..." \
  -H "Content-Type: application/json" \
  -d '{
    "customer_id": "8cc6199f-9466-46f2-9db7-936f3c2c1c0b",
    "agent_id": "ddb8be3b-a426-4122-b877-a0cba363c89d",
    "variables": {
      "appointment_time": "Thursday March 20th at 2:00 PM",
      "doctor_name": "Dr. Patel"
    }
  }'
```

```json Response theme={null}
{
  "notification": {
    "id": "13eea9cc-dbad-897d-35d9-fa46a5e30971",
    "status": "in_progress",
    "target_phone_e164": "+14155552671"
  },
  "call": {
    "callId": "call-abc123",
    "status": "queued"
  }
}
```

Echo immediately initiates the outbound call. The call happens in real time — Echo will POST results to your webhook once the call ends.

***

## Step 5 — Receive the webhook

After the call ends, Echo sends a signed event to your webhook endpoint. First, register an endpoint:

```bash theme={null}
curl -X POST https://api.meetecho.ai/v1/projects/{projectId}/webhooks \
  -H "x-api-key: echo_6f437a610fbb..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-server.com/webhooks/echo",
    "events": ["call.summary"]
  }'
```

Save the `signing_secret` from the response — use it to verify the `X-Echo-Signature` header on every delivery.

Then verify the signature and process the payload on your server:

```javascript theme={null}
const crypto = require('crypto');

app.post('/webhooks/echo', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = crypto
    .createHmac('sha256', process.env.ECHO_SIGNING_SECRET)
    .update(req.body) // raw Buffer — not parsed JSON
    .digest('hex');

  if (`sha256=${sig}` !== req.headers['x-echo-signature']) {
    return res.status(401).send('Invalid signature');
  }

  const { event_name, data } = JSON.parse(req.body);

  if (event_name === 'call.summary') {
    console.log(data.analysis);
    // { confirmed: true, reschedule_request: null }
  }

  res.sendStatus(200);
});
```

The `data.analysis` field contains the structured data extracted from the call using your agent's `output_schema`.

***

## What's next

<CardGroup cols={2}>
  <Card title="Agent approach guide" icon="robot" href="/guides/agent-approach">
    Deep dive into agents, prompts, output schemas, and variables.
  </Card>

  <Card title="LLM path guide" icon="wand-magic-sparkles" href="/guides/llm-approach">
    Send a plain message without defining an agent.
  </Card>

  <Card title="Writing prompts" icon="pen-fancy" href="/guides/writing-prompts">
    Craft effective system prompts for consistent, reliable calls.
  </Card>

  <Card title="Webhooks" icon="webhook" href="/guides/webhooks">
    Full webhook reference including payload shape and signature verification.
  </Card>
</CardGroup>
