
# Migrate to Espresso

Espresso is a market and business intelligence API for discovering market actions, signals, and tracing concrete evidence. If you want to know

- **What happened?** Search **Events** for concrete developments.
- **What does it mean?** Search **Signals** for synthesized conclusions, then retrieve supporting Events when the answer needs substantiation.

Espresso out performs other market intelligence APIs with 2 distinctive features:
- **Synthesized Signals**: In addition micro-actions and events, Espresso synthesizes related tangential events and actions into consolidated signals which higher data enrichment such as causal event chains, multi-domain impacts and forecasts.
- **Token Efficiency**: Espresso is built to be AI agent native and can provide responses in both yaml and toon in addition to default json. This is particularly helpful in reducing input tokens while maintaining the same data fidelity.

It is not a drop-in replacement for an article archive. Use Beans API for that.

## Choose the right target

| If your current workflow needs | Use Espresso | Notes |
| --- | --- | --- |
| Structured developments about a company, person, product, region, or topic | `GET /espresso/events` | Events are the primary starting point for concrete developments. |
| A higher-level interpretation or expected impact | `GET /espresso/signals` | Signals are synthesized conclusions, not raw observations. |
| Support, source coverage, or traceability for one Event | `GET /espresso/events/{event_id}/evidence` | Returns directly related evidence records, not article bodies. |
| The concrete developments behind one conclusion | `GET /espresso/signals/{signal_id}/events` | Use after selecting a Signal. |
| Source metadata or a source-specific Event set | `GET /espresso/sources` then `GET /espresso/events?source_ids=...` | Source search is metadata matching, not semantic search. |
| Full article text, a content archive, or story clustering | [Beans](/products/beans) or another content source | Espresso returns intelligence records and available provenance, not article bodies. |

## Translate the data model

| Familiar concept | Espresso concept | How an agent should use it |
| --- | --- | --- |
| Event, incident, or development | **Event** | Search `GET /espresso/events`; preserve `data[].id` for detail, evidence, and related Signals. |
| Story, assessment, insight, or forecast | **Signal** | Search `GET /espresso/signals`; preserve `data[].id` to inspect its support. |
| Supporting documents or related coverage | **Evidence** | Request evidence only for a selected Event when provenance or context is needed. |
| Publisher or source record | **Source** | Resolve a Source by metadata, then reuse its UUID in `source_ids`. |
| Topic label or theme | **Tag** | Use `tags` as a fuzzy text filter. |
| Type, category, company, person, product, or region filter | Exact Event filter | Send normalized snake_case values. `categories` and `event_types` are separate fields. |

## Route migration

Start from a collection, select an ID, and retrieve more context only when it changes the answer.

| Common existing pattern | Espresso route sequence |
| --- | --- |
| Search structured events, then open one result | `GET /espresso/events` → `GET /espresso/events/{event_id}` |
| Search an insight, then explain it | `GET /espresso/signals` → `GET /espresso/signals/{signal_id}` → `GET /espresso/signals/{signal_id}/events` |
| Open an event, then check supporting context | `GET /espresso/events/{event_id}` → `GET /espresso/events/{event_id}/evidence` |
| Find records from a known publisher or domain | `GET /espresso/sources` → `GET /espresso/events?source_ids={source_id}` |
| Find related conclusions for a known development | `GET /espresso/events/{event_id}/signals` → `GET /espresso/signals/{signal_id}` |

Collections provide enough information to choose relevant IDs; detail and relationship routes are targeted follow-up calls.

## GDELT and Perigon concept map

These mappings describe typical user jobs, not identical schemas or coverage.

| GDELT or Perigon pattern | Espresso interpretation |
| --- | --- |
| Event search | `GET /espresso/events` |
| Event detail | `GET /espresso/events/{event_id}` |
| Story or article evidence | Event evidence and Source routes |
| Signal or semantic interpretation | `GET /espresso/signals` |
| Supporting event traversal | `GET /espresso/signals/{signal_id}/events` |
| Entity, region, and event-type discovery | Espresso discovery routes |
| Source or publisher context | Espresso Sources |
| Free-text or semantic search | `q` on supported collection routes |
| Cursor continuation | `cursor` and `next_cursor` |


## Adapt queries and filters

| Existing query intent | Espresso parameter | Matching rule |
| --- | --- | --- |
| Natural-language topic or question | `q` on Event or Signal search | Semantic search. |
| Semantic search strictness | `score_threshold` with `q` | Minimum similarity threshold from `0.0` (broad) to `1.0` (strict); default `0.5`. |
| Topic, theme, or label | `tags` | Fuzzy text matching. |
| Event type | `event_types` | Exact normalized snake_case value. |
| Category | `categories` | Exact normalized snake_case value; separate from `event_types`. |
| Company or person name | `companies`, `people`, or `entities` | Exact normalized snake_case value. `entities` matches company or people names. |
| Product, region, or impact level | `products`, `regions`, `impact_levels` | Exact normalized snake_case value where applicable. |
| Signal domain | `impacted_domains` | Exact normalized snake_case value on Signal routes. |
| Source | `source_ids` | Source UUID, not a domain or display name. |

Use `GET /espresso/tags`, `/event-types`, `/entities`, or `/regions` only when your client does not already have a suitable filter value. Discovery output is vocabulary for filtering, not a canonical entity or geography service.

## Adapt pagination and responses

Espresso collections return one stable envelope:

```json
{
  "data": [],
  "pagination": {
    "limit": 20,
    "num_results": 0,
    "next_cursor": null
  },
  "meta": {
    "as_of": "2026-08-19T00:00:00Z"
  }
}
```

- `pagination.num_results` counts only the records in this page. It is not a total-match count.
- Send a non-null `pagination.next_cursor` unchanged as the next request `cursor`. Never construct, decode, or sort the token.
- An empty collection is a successful HTTP `200` response with `data: []`.
- Detail routes return `{ "data": { ... } }`; a missing detail resource returns HTTP `404`.
- Errors use `{ "error": { "code", "message" } }`. REST calls except health require Bearer authentication.

Stable Event and Signal fields are `id`, `kind`, `created_at`, and `tags`. Treat `summary`, `key_points`, `impacts`, `source`, `links`, `counts`, and any other keys as conditional or extension fields.

Use `response_type=json` for the canonical schema. `response_type=yaml` and `response_type=toon` contain the same payload in token-optimized forms for MCP and AI-agent workflows. They do not change the filters, records, or pagination behavior.

## Migration checklist

1. Classify each old request as an Event question, a Signal question, a provenance question, or a source question.
2. Change collection parsing to read `data`, `pagination`, and `meta`.
3. Store returned Event, Signal, and Source UUIDs as opaque identifiers.
4. Replace offset or cursor construction with pass-through use of `pagination.next_cursor`.
5. Separate fuzzy `tags` from exact structured filters, and keep `categories` distinct from `event_types`.
6. Treat `from` and `to` as `created_at` bounds.
7. Use evidence and supporting-Event routes only after a selected record requires explanation or traceability.
8. Use JSON for schema-sensitive parsers; opt into YAML or TOON for token-sensitive agent calls.

## Next steps

- [Espresso overview and quickstart](/products/espresso)
- [Espresso workflows and scenarios](/products/espresso/workflows)
- [Espresso API reference](/api/espresso)
- [MCP & AI agents](/guides/mcp-ai-agents)
