# Ambient REST API Developer Guide  
Written by Taylor McLoughlin  
March 24, 2026

# Overview  
The Ambient REST API gives you programmatic access to your organization's meeting summaries, transcripts, email summaries, Slack digests, projects, files, and AI-generated insights. It is a read-only, RESTful JSON API designed for AI workflows and integrations.

**Base URL:** [`https://api.ambient.us/v1`](https://api.ambient.us/v1)  
If you are looking for MCP (Model Context Protocol) integration instead, see our [MCP documentation](https://help.ambient.us/en/articles/14053674-get-started-with-ambient-mcp). This guide covers the standalone REST API only.

---

# Authentication  
All requests require an API key passed as a Bearer token in the `Authorization` header.

**curl**  
```
curl -H "Authorization: Bearer YOUR_API_KEY" \   https://api.ambient.us/v1/whoami
```

**Python**  
```
import requests  
API_KEY = "YOUR_API_KEY"  
BASE_URL = "https://api.ambient.us/v1"  
HEADERS = {"Authorization": f"Bearer {API_KEY}"}  
response = requests.get(f"{BASE_URL}/whoami", headers=HEADERS)  
print(response.json())
```

**JavaScript**  
```
const API_KEY = "YOUR_API_KEY";  
const BASE_URL = "https://api.ambient.us/v1";  
const response = await fetch(`${BASE_URL}/whoami`, {   headers: { Authorization: `Bearer ${API_KEY}` }, });  
const data = await response.json();  
console.log(data);
```  
The `/whoami` endpoint returns your key type, user details, organization ID, and granted scopes. Use it to verify your key is working.

## Key types  
|     |     |
| --- | --- |
| Key type | Description |
| `user` | Scoped to a specific user within an organization |
| `user_org` | A user key with organization-wide access |
| `org` | Organization-wide access without a specific user |

To get an API key, visit **Workspace Settings** in the Ambient app.

---

# Core concepts  
## Resource types  
Ambient organizes data into a few core resource types:  
|     |     |     |
| --- | --- | --- |
| Resource | Description | ID prefix |
| **Artifacts** | Meeting summaries, email summaries, and Slack digests | `art_` |
| **Meetings** | Calendar meetings with attendee info | `mtg_` |
| **Insights** | AI-generated content like meeting dossiers and daily briefings | `ins_` |
| **Projects** | Organizational groupings for artifacts and files | `prj_` |
| **Files** | Uploaded documents associated with projects | `fil_` |

All IDs use a type-prefixed format (e.g., `art_550e8400-e29b-41d4-a716-446655440000`). The prefix and ID value are stable and will not change for a given resource.

## Expansions (the `include` parameter)  
To keep responses lightweight, most content fields are omitted by default. Use the `include` query parameter to expand the fields you need. Pass multiple expansions as a comma-separated list.

For example, to get artifact text content and attendees:  
```
GET /v1/artifacts?include=text_content,attendees
```  
Each resource type supports different expansions, documented in the endpoint sections below.

## Pagination  
All list endpoints use cursor-based pagination.  
|     |     |
| --- | --- |
| Parameter | Description |
| `limit` | Number of results per page (1-200, default 50) |
| `cursor` | Opaque cursor returned as `next_cursor` in the previous response |

When `next_cursor` is `null`, there are no more results.

**Python example: paginating through all artifacts**  
```
cursor = None  
while True:  
    params = {"limit": 100, "include": "text_content"}  
    if cursor:  
        params["cursor"] = cursor  
    response = requests.get(f"{BASE_URL}/artifacts", headers=HEADERS, params=params)  
    data = response.json()  
    for artifact in data["data"]:  
        print(artifact["title"])  
    cursor = data.get("next_cursor")  
    if not cursor:  
        break
```

---

# Endpoints  
## Artifacts  
Artifacts are the primary content objects in Ambient. They come in three types:  
|     |     |
| --- | --- |
| Type | Description |
| `meeting_summary` | Generated from a recorded meeting |
| `email_summary` | Generated from connected email |
| `slack_digest` | Generated from connected Slack channels |

## List artifacts  
```
GET /v1/artifacts
```  
**Query parameters:**  
|     |     |     |
| --- | --- | --- |
| Parameter | Type | Description |
| `type` | string | Filter by artifact type: `meeting_summary`, `email_summary`, `slack_digest` |
| `project_id` | string | Filter to artifacts in a specific project |
| `meeting_id` | string | Filter to artifacts from a specific meeting |
| `q` | string | Search artifact titles (case-insensitive substring match) |
| `attendee_email` | string | Filter to artifacts from meetings with this attendee |
| `attendee_domain` | string | Filter by attendee email domain (e.g., `acme.com`) |
| `status` | string | `published` (default), `draft`, or `any` |
| `created_after` | datetime | Only return artifacts created after this timestamp |
| `updated_after` | datetime | Only return artifacts updated after this timestamp |
| `order` | string | `created_at:asc`, `created_at:desc`, `effective_date:asc`, `effective_date:desc` |
| `include` | string | Comma-separated: `text_content`, `json_content`, `meeting`, `transcript`, `action_items`, `project_ids`, `attendees` |
| `limit` | integer | Results per page (1-200, default 50) |
| `cursor` | string | Pagination cursor |

## Get a single artifact  
```
GET /v1/artifacts/{artifact_id}
```
Supports the same `include` parameter as the list endpoint.

---

# Meetings  
Meetings represent calendar events from connected calendars.  
## List meetings  
```
GET /v1/meetings
```  
**Query parameters:**  
|     |     |     |
| --- | --- | --- |
| Parameter | Type | Description |
| `ical_uid` | string | Filter by iCal UID |
| `q` | string | Search meeting titles (case-insensitive substring match) |
| `attendee_email` | string | Filter to meetings with this attendee |
| `attendee_domain` | string | Filter by attendee email domain |
| `starts_at_gte` | datetime | Meetings starting at or after this time |
| `starts_at_lte` | datetime | Meetings starting at or before this time |
| `include_shared` | boolean | Include meetings where you have access to a linked artifact (default: false) |
| `order` | string | `starts_at:asc`, `starts_at:desc` |
| `include` | string | Comma-separated: `attendees`, `artifacts`, `insights` |
| `limit` | integer | Results per page (1-200, default 50) |
| `cursor` | string | Pagination cursor |

## Get a single meeting  
```
GET /v1/meetings/{meeting_id}
```

---

## Insights  
Insights are AI-generated content like pre-meeting dossiers and daily briefings.  
|     |     |
| --- | --- |
| Type | Description |
| `meeting_dossier` | Pre-meeting research: attendee context, related meetings, conversation starters |
| `daily_briefing` | Once-a-day summary of upcoming meetings |

## List insights  
```
GET /v1/insights
```  
**Query parameters:**  
|     |     |     |
| --- | --- | --- |
| Parameter | Type | Description |
| `type` | string | Filter by type: `meeting_dossier`, `daily_briefing` |
| `resource_id` | string | Filter by related resource (e.g., a meeting ID for dossiers) |
| `created_after` | datetime | Only return insights created after this timestamp |
| `order` | string | `created_at:asc`, `created_at:desc` |
| `include` | string | Comma-separated: `text_content`, `json_content`, `meeting` |
| `limit` | integer | Results per page (1-200, default 50) |
| `cursor` | string | Pagination cursor |

## Get a single insight  
```
GET /v1/insights/{insight_id}
```

---

## Projects  
Projects are organizational groupings for artifacts and files.  
## List projects  
```
GET /v1/projects
```  
Returns active projects only (archived projects are excluded).  
## Get a single project  
```
GET /v1/projects/{project_id}
```
## List artifacts in a project  
```
GET /v1/projects/{project_id}/artifacts
```
Supports the same query parameters and `include` options as the main artifacts list endpoint.  
## List files in a project  
```
GET /v1/projects/{project_id}/files
```

---

## Files  
Files are documents uploaded to projects.  
## List files  
```
GET /v1/files
```  
**Query parameters:**  
|     |     |     |
| --- | --- | --- |
| Parameter | Type | Description |
| `project_id` | string | Filter to files in a specific project |
| `updated_after` | datetime | Only return files updated after this timestamp |
| `order` | string | `updated_at:asc`, `updated_at:desc`, `created_at:asc`, `created_at:desc` |
| `include` | string | Comma-separated: `text_content`, `generated_summary`, `project_ids` |
| `limit` | integer | Results per page (1-200, default 50) |
| `cursor` | string | Pagination cursor |

**Note:** When using `include=text_content` on list endpoints, the server may return a 400 error if the combined content is too large. Use the single-file endpoint for large text content.  
## Get a single file  
```
GET /v1/files/{file_id}
```

---

# Common workflows  
## Pull transcripts with participant info  
This is the most common integration pattern. A single API call retrieves meeting transcripts alongside attendee details.  
**curl**  
```
curl -H "Authorization: Bearer YOUR_API_KEY" \   "https://api.ambient.us/v1/artifacts?type=meeting_summary&include=transcript,attendees&order=effective_date:desc&limit=10"
```  
**Python**  
```
response = requests.get(     f"{BASE_URL}/artifacts",     headers=HEADERS,     params={         "type": "meeting_summary",         "include": "transcript,attendees",         "order": "effective_date:desc",         "limit": 10,     }, )  
for artifact in response.json()["data"]:     print(f"\n--- {artifact['title']} ---")      # Attendees     if artifact.get("attendees"):         for attendee in artifact["attendees"]:             role = " (organizer)" if attendee["is_organizer"] else ""             print(f"  {attendee.get('display_name', 'Unknown')} <{attendee.get('email', 'N/A')}>{role}")      # Transcript     transcript = artifact.get("transcript", {})     if transcript and transcript.get("disposition") == "AVAILABLE":         print(f"\nTranscript:\n{transcript['text_content'][:500]}...")
```  
**JavaScript**  
```
const response = await fetch(   `${BASE_URL}/artifacts?type=meeting_summary&include=transcript,attendees&order=effective_date:desc&limit=10`,   { headers: { Authorization: `Bearer ${API_KEY}` } } ); 
const { data: artifacts } = await response.json();  
for (const artifact of artifacts) {   console.log(`\n--- ${artifact.title} ---`);    // Attendees   artifact.attendees?.forEach((a) => {     const role = a.is_organizer ? " (organizer)" : "";     console.log(`  ${a.display_name ?? "Unknown"} <${a.email ?? "N/A"}>${role}`);   });    // Transcript   if (artifact.transcript?.disposition === "AVAILABLE") {     console.log(`\nTranscript:\n${artifact.transcript.text_content.slice(0, 500)}...`);   } }
```
The transcript is returned as plain text with speaker labels and timecodes. Each line follows the format `[m:ss] Speaker: text` (or `[h:mm:ss]` for longer recordings).  
## Find meetings with a specific person or company  
Filter artifacts by attendee email or email domain:  
```
# All meetings with a specific person 
curl -H "Authorization: Bearer YOUR_API_KEY" \   "https://api.ambient.us/v1/artifacts?attendee_email=jane@acme.com&include=text_content,attendees"  
# All meetings with anyone from a company 
curl -H "Authorization: Bearer YOUR_API_KEY" \   "https://api.ambient.us/v1/artifacts?attendee_domain=acme.com&include=text_content,attendees"
```  
## Get meeting summaries with action items  
```
curl -H "Authorization: Bearer YOUR_API_KEY" \   "https://api.ambient.us/v1/artifacts?type=meeting_summary&include=text_content,action_items&order=effective_date:desc&limit=5"
```  
Action items include a description, status (`OPEN`, `DONE`, `INPROGRESS`), importance level, optional due date, and an owner with name and email when available.  
## Get pre-meeting dossiers  
Retrieve AI-generated research for upcoming meetings:  
```
# Get dossier for a specific meeting 
curl -H "Authorization: Bearer YOUR_API_KEY" \   "https://api.ambient.us/v1/insights?type=meeting_dossier&resource_id=mtg_YOUR_MEETING_ID&include=text_content"  
# Get recent dossiers 
curl -H "Authorization: Bearer YOUR_API_KEY" \   "https://api.ambient.us/v1/insights?type=meeting_dossier&include=text_content&order=created_at:desc&limit=5"
```  
## Sync new artifacts since last pull  
Use `created_after` or `updated_after` to implement incremental sync:  
```
from datetime import datetime, timezone  
# Store this timestamp between sync runs  
last_sync = "2026-03-01T00:00:00Z"  
response = requests.get(     f"{BASE_URL}/artifacts",     headers=HEADERS,     params={         "updated_after": last_sync,         "include": "text_content,attendees",         "order": "created_at:asc",         "limit": 200,     }, )  
artifacts = response.json()["data"]  
print(f"Found {len(artifacts)} new/updated artifacts since {last_sync}")  
# Update last_sync to now for next run  last_sync = datetime.now(timezone.utc).isoformat()
```  
---

## Error handling  
The API returns standard HTTP status codes with structured error responses:  
```
{   "error": {     "code": "not_found",     "message": "Artifact not found",     "request_id": "req_01HZZ..."   } }
```
|     |     |
| --- | --- |
| Status | Meaning |
| 200 | Success |
| 400 | Bad request (invalid parameters, response too large) |
| 401 | Unauthorized (invalid or missing API key) |
| 404 | Resource not found or not accessible |

Include the `request_id` from error responses when contacting support.  
---

## Rate limits and best practices  
- Use `include` selectively. Only request the expansions you need to keep responses fast and small.  
- Paginate with reasonable page sizes. The default of 50 works well for most use cases. The maximum is 200.  
- Use `created_after` / `updated_after` for incremental sync rather than re-fetching everything.  
- When using `include=text_content` on list endpoints, be aware the server may reject requests where the combined content is too large. Use the single-resource endpoint as a fallback.  
- Cache the `next_cursor` value if your process might be interrupted mid-pagination.  
---

## Need help?  
If you have questions or run into issues, reach out to us at [support@ambient.us](mailto:support@ambient.us) or through the in-app chat.
