# API quick start | GTM and Outreach

Source: https://exntra.in/api/quickstart

# From an API key to a running campaign

Four requests: connect a mailbox, import contacts, create a campaign, then check, test and launch. Create your key in Settings, then API & MCP.

**Before you start.** Every request needs `Authorization: Bearer gtm_...`. Replace `api.yourdomain.com` with your API address. Times are ISO 8601 in UTC.

 

```
// A tiny helper used in the JavaScript examples
const BASE = "https://api.yourdomain.com/v1";
async function api(method, path, body) {
  const res = await fetch(BASE + path, {
    method,
    headers: { Authorization: "Bearer " + process.env.GTM_KEY, "content-type": "application/json" },
    body: body ? JSON.stringify(body) : undefined,
  });
  const data = await res.json();
  if (!res.ok) throw new Error(data.error); // errors are plain sentences
  return data;
}
```

1.  ## Connect a mailbox
    
    Use an app password for Google Workspace or Zoho, or any SMTP/IMAP server. We test the login before saving. New mailboxes start with a slow start; add "slowStart": false if it's already warmed up.
    
     
    
    ```
    API=https://api.yourdomain.com/v1
    KEY="Authorization: Bearer gtm_..."
    
    curl -X POST $API/mailboxes/smtp -H "$KEY" -H 'content-type: application/json' \
      -d '{"email":"sam@acme.com","name":"Sam","password":"app-password","provider":"google"}'
    ```
    
    ```
    await api("POST", "/mailboxes/smtp", {
      email: "sam@acme.com", name: "Sam", password: "app-password", provider: "google",
    });
    ```
    
2.  ## Import contacts
    
    Send rows directly, or a Google Sheets link. Every address is checked. The response tells you how many were imported and what was left out.
    
     
    
    ```
    curl -X POST $API/contacts/import -H "$KEY" -H 'content-type: application/json' \
      -d '{"listName":"SaaS founders","rows":[
            {"email":"ana@startup.io","first_name":"Ana","company":"Startup"},
            {"email":"raj@fintech.in","first_name":"Raj","company":"Fintech"}]}'
    
    # {"listId":"...","imported":2,"verification":{"valid":2,"role":0,"disposable":0,"no_mail_server":0}, ...}
    ```
    
    ```
    const { listId, imported, verification } = await api("POST", "/contacts/import", {
      listName: "SaaS founders",
      rows: [{ email: "ana@startup.io", first_name: "Ana", company: "Startup" }],
    });
    ```
    
3.  ## Create the campaign
    
    A campaign starts as a draft. Steps with an empty subject go out as replies in the same thread.
    
     
    
    ```
    curl -X POST $API/campaigns -H "$KEY" -H 'content-type: application/json' -d '{
      "name": "Founders Q4", "listIds": ["LIST_ID"], "mailboxIds": ["MAILBOX_ID"], "dailyLimit": 30,
      "window": {"start":"10:00","end":"17:00","tz":"Asia/Kolkata","days":["Mon","Tue","Wed","Thu","Fri"]},
      "steps": [
        {"waitDays":0,"subject":"{Quick|Short} question, {{first_name|there}}","body":"Hi {{first_name|there}},\n\n...","format":"plain"},
        {"waitDays":3,"subject":"","body":"Bumping this up, {{first_name|there}}.","format":"plain"}
      ]}'
    ```
    
    ```
    const { campaign } = await api("POST", "/campaigns", {
      name: "Founders Q4", listIds: [listId], mailboxIds: [mailboxId], dailyLimit: 30,
      window: { start: "10:00", end: "17:00", tz: "Asia/Kolkata", days: ["Mon","Tue","Wed","Thu","Fri"] },
      steps: [
        { waitDays: 0, subject: "{Quick|Short} question, {{first_name|there}}", body: "Hi {{first_name|there}},\n\n...", format: "plain" },
        { waitDays: 3, subject: "", body: "Bumping this up, {{first_name|there}}.", format: "plain" },
      ],
    });
    ```
    
4.  ## Check, test, then launch
    
    The check lists anything that would block the launch. Send yourself every step as a test, then launch. An account's first campaign gets a short content review before it starts.
    
     
    
    ```
    curl $API/campaigns/CAMPAIGN_ID/check -H "$KEY"
    
    curl -X POST $API/campaigns/CAMPAIGN_ID/test -H "$KEY" -H 'content-type: application/json' \
      -d '{"to":"you@yourcompany.com","allSteps":true}'
    
    curl -X POST $API/campaigns/CAMPAIGN_ID/launch -H "$KEY"
    ```
    
    ```
    const check = await api("GET", `/campaigns/${id}/check`);
    if (check.blocking.length) throw new Error(check.blocking.join(", "));
    await api("POST", `/campaigns/${id}/test`, { to: "you@yourcompany.com", allSteps: true });
    await api("POST", `/campaigns/${id}/launch`);
    ```
    

**Then what?** Watch replies with `GET /inbox` or the `email.replied` webhook. Answer with `POST /inbox/:id/reply`. Check quotas and rate-limit headroom with `GET /limits`. The full reference is at `/v1/docs` on your API.

## Try it on your own mailbox

Your first month is free. Create a key and run the four steps above.

[Start your free month](https://app.example.com/#/signup)[Talk to us](/contact)
