---
title: "FirstSales API Quickstart | FirstSales"
description: "Generate an API key and make your first calls — create contacts, enroll them in campaigns, and pull replies from the inbox over the REST API."
canonical: "https://firstsales.io/tutorial/api-quickstart/"
---

[Home](/)/[Tutorials](/tutorial/)/FirstSales API Quickstart

Developer & CLI

# FirstSales API Quickstart

Generate an API key and make your first calls — create contacts, enroll them in campaigns, and pull replies from the inbox over the REST API.

9 min read·Advanced·7 steps

1. 1  
## Generate a Developer API key  
In the app go to **Settings → API** and create a Developer API key. Set its **scopes** and **access level** (read vs read-write) to the minimum the integration needs. The secret is shown **once** — copy it into a secret manager immediately; the app only stores a redacted form.  
Revoke and regenerate on the same page if a key ever leaks.
2. 2  
## Verify identity with whoami  
The base URL is `https://api.app.firstsales.io`. Auth is a **Bearer** token. Always start by confirming the key resolves to the org and workspace you expect — `GET /api/v1/whoami`:  
```  
curl https://api.app.firstsales.io/api/v1/whoami \  
  -H "Authorization: Bearer $FIRSTSALES_API_KEY"  
```
3. 3  
## Find your org and workspace IDs  
Every resource is scoped to an **organization** and a **workspace**, so most paths look like `/api/v1/organizations/{orgId}/workspaces/{workspaceId}/…`. List them:  
```  
# Organizations you can access  
curl https://api.app.firstsales.io/api/v1/organizations \  
  -H "Authorization: Bearer $FIRSTSALES_API_KEY"  
# Workspaces inside an org  
curl https://api.app.firstsales.io/api/v1/organizations/ORG_ID/workspaces \  
  -H "Authorization: Bearer $FIRSTSALES_API_KEY"  
```
4. 4  
## Create a contact (idempotently)  
POST a contact into a workspace. Pass an **Idempotency-Key** header so a retried request never creates a duplicate — safe to replay on network failure.  
```  
curl -X POST \  
  https://api.app.firstsales.io/api/v1/organizations/ORG_ID/workspaces/WS_ID/contacts \  
  -H "Authorization: Bearer $FIRSTSALES_API_KEY" \  
  -H "Content-Type: application/json" \  
  -H "Idempotency-Key: jane-acme-2026-01" \  
  -d '{ "email": "jane@acme.com", "first_name": "Jane", "company_name": "Acme" }'  
```
5. 5  
## Read campaign analytics  
Pull funnel and engagement metrics for a campaign to sync results into your own reporting — no scraping the dashboard:  
```  
curl https://api.app.firstsales.io/api/v1/organizations/ORG_ID/workspaces/WS_ID/campaigns/CAMPAIGN_ID/analytics \  
  -H "Authorization: Bearer $FIRSTSALES_API_KEY"  
```
6. 6  
## Read replies from the inbox  
List inbox threads to pull sends, opens, replies, and bounces into your systems. Thread bodies are redacted in the list view; fetch a single thread for detail. This is how you route positive replies into a CRM while native connectors are still coming.  
```  
curl https://api.app.firstsales.io/api/v1/organizations/ORG_ID/workspaces/WS_ID/inbox/threads \  
  -H "Authorization: Bearer $FIRSTSALES_API_KEY"  
```
7. 7  
## Stay inside the public surface  
The API only exposes the public `/api/v1` surface. **Don't** call app-private routes, provider callbacks, tracking pixels, unsubscribe handlers, or internal cron routes — they aren't part of the contract and will break. If a call returns `unsupported_operation`, stop and treat it as "not available via the API," not something to work around.  
Standard status codes apply: `401` bad/revoked key, `422` validation (body names the field), `429` rate-limited (back off and retry).

## Pro tips

Hard-won shortcuts that keep warm-up on track.

1

### whoami before you write

Confirm the key resolves to the org/workspace you intend before any mutating call. A key scoped to the wrong workspace is the most common way to write data into the wrong place.

2

### Always send an Idempotency-Key on creates

Network retries happen. An Idempotency-Key makes a replayed POST a no-op instead of a duplicate contact or double charge.

3

### Store the key once, never print it

The secret is shown a single time and stored redacted. Put it straight into a secret manager; never log it, commit it, or ship it in a client bundle.

4

### Treat unsupported\_operation as a hard stop

If the API returns unsupported\_operation, the thing you want isn't in the public contract. Don't reach for app-private routes to force it — report the limitation.

## Frequently asked questions

Where do I get an API key?

**Settings → API**. Create a Developer API key with the scopes and access level you need; it's shown once, so copy it immediately. Revoke and regenerate on the same page if it's exposed.

What's the base URL and auth?

Base URL `https://api.app.firstsales.io`; authenticate with `Authorization: Bearer $FIRSTSALES_API_KEY` and send JSON. Start with `GET /api/v1/whoami` to confirm context.

Why are the paths so long?

Resources are scoped to an org and workspace, so paths are `/api/v1/organizations/{orgId}/workspaces/{workspaceId}/…`. Get the IDs from `/api/v1/organizations` and its `/workspaces` sub-resource (or from `whoami`).

How do I avoid duplicate writes?

Send an **Idempotency-Key** header on create requests. A retried request with the same key returns the original result instead of creating a second record — safe to replay after a timeout.

Can I read campaign metrics and replies?

Yes — `GET …/campaigns/{id}/analytics` for funnel/engagement, and `GET …/inbox/threads` for conversation activity. Thread bodies are redacted in the list; fetch a single thread for full detail.

Is there a Zapier or CRM integration instead?

No Zapier connector, and native CRM connectors (Salesforce, HubSpot, Pipedrive) are still coming. Until they ship, the REST API — or the CLI — is the supported way to integrate and sync.

What does unsupported\_operation mean?

The requested action isn't part of the public `/api/v1` contract. Stop and report it — don't call app-private routes, callbacks, pixels, or internal endpoints to work around it; those aren't supported and will break.

## Ready to put this into practice?

Start your FirstSales trial and launch a warmed, authenticated mailbox in minutes.

[Start for $1](https://app.firstsales.io)

[All tutorials](/tutorial/)