# Together — agent integration profile

Together is a private dealflow tool for a small, trusted circle. It records when a
user and the people they've added cross paths on the same companies, decks, and
founder profiles, and surfaces what their circle knows — notes, tags, presence —
on the page they're already on.

This file is for AI agents and codegen tools. If you're wiring Together into a
dealflow tracker, a CRM, or your own agent, start here. (Human guide:
https://together.brdg.app/developers)

## What you can do

Check a user in at a URL and get back who in *their* circle has been at the same
place — the same matches they'd see in the app. Visibility is enforced
server-side: you only ever see check-ins from people the user has mutually added,
never strangers.

## Base URL

```
https://together.brdg.app/api/v1
```

## Auth

Every request carries one header:

```
Authorization: Bearer <key>
```

`<key>` is a Bridge API key (the identity layer behind Together), minted by the
user from their Bridge account at https://brdg.app/account/. No cookies, no second
key. Every query runs under the user's own permissions — the API can never see
more than the user can.

Verify a key:

```
curl -H "Authorization: Bearer $KEY" https://together.brdg.app/api/v1/healthz
```

A 200 with the user id means you're set.

## Primary endpoint — check in and match

`POST /api/v1/checkins/match`

```
curl -X POST https://together.brdg.app/api/v1/checkins/match \
  -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://stripe.com/pricing"}'
```

Pass any company URL, LinkedIn profile, or doc/deck (DocSend, Google Docs, Figma,
GitHub, …); params are stripped and the URL is classified the same way the
extension does. Optional body fields: `comment` (string), `tags` (string[]),
`category` (string), `target_title` (string), `limit` (1–100, default 50).
Untrackable URLs (search pages, internal surfaces) return 400. Repeat check-ins at
the same target within 24h dedupe into one row (`deduped: true`).

## CRM lookup — is this target already in the user's CRM?

`GET /api/v1/crm/check`

Read-only (records nothing). Reports whether the user has a CRM connected (Attio
today) and, when you pass a target, whether that company or person is already in
it. Useful before you act on a target — qualify it against the user's existing
pipeline first.

```
curl -H "Authorization: Bearer $KEY" \
  "https://together.brdg.app/api/v1/crm/check?url=https://stripe.com"
```

A missing CRM is a normal `200` with `configured: false` — not an error — so you
branch on connection state without catching. Pass a `url` (classified
server-side, same as the match endpoint) or a pre-classified `target_kind` +
`target_key`; omit the target entirely for a pure "is a CRM connected?" probe.
When connected, `in_crm` says whether the target exists and `matches[]` carries
the CRM record(s) (`id`, `name`, deep-link `url`, and any `lists`). Artifacts
(docs, decks) aren't tracked by CRMs → `in_crm: false`. A connected-but-rejected
token returns `401`; a provider rate-limit/failure returns `502`.

## Watchlist — list, add, and remove watched targets

`GET / POST / DELETE /api/v1/watchlist`

The user's watchlist is a standing subscription: when anyone in their circle
checks in on or notes a watched company/person, they get a Together-bot DM.
Private to the user. Add by URL — classified + hashed server-side, so you never
compute a hash:

```
curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"url":"https://stripe.com"}' \
  "https://together.brdg.app/api/v1/watchlist"
```

Returns `{ watch, created }` — `created: false` when already watching (idempotent).
List with `?limit=&offset=` (`{ data: [...], meta }`), then unwatch by the row's
`id`: `DELETE /api/v1/watchlist/<id>` → `{ ok: true }` (soft delete; a later
note-auto-watch won't re-add a dismissed target). First-party clients may POST a
pre-hashed `target_kind` + `target_key_hash` instead of `url`.

## Activity timeline — read the user's circle feed

`GET /api/v1/activity`

The feed that powers the app's Activity page: the user's circle's activity, newest
first, scoped to the user and their accepted friends. A row appears when a
check-in carries intent (comment or tags) or has a visible note attached. Each row
is a check-in enriched with note metadata (`note_count`, `note_preview`,
`note_latest_at`, …).

```
curl -H "Authorization: Bearer $KEY" \
  "https://together.brdg.app/api/v1/activity?limit=20&tag=dealflow"
```

Query params (all optional): `q` (free-text over check-in comment / target / host,
author name + username, note body), `start` / `end` / `since` (ISO 8601),
`target_kind` (`company` | `person` | `artifact`), `target_key_hash`, `tag`
(repeatable, ALL must match), `limit` (1–100, default 50), `offset`. Returns
`{ data: [...check-in rows], meta: { total, limit, offset } }`.

## Machine-readable spec

- OpenAPI 3.1: https://together.brdg.app/api/v1/openapi.json
- One-page guide: https://together.brdg.app/llms.txt

## Full docs

- Human guide: https://together.brdg.app/developers
- Quickstart: https://together.brdg.app/docs/api-quickstart.md
- Errors: https://together.brdg.app/docs/api-errors.md
(Endpoint reference is the OpenAPI spec linked above.)

## Good to know

- You only ever see check-ins from people the user has mutually added — never strangers.
- The same URL classification powers the API and the extension, so an API check-in on
  `linkedin.com/in/jane` or a `docsend.com/view/<code>` deck matches a friend who hit the
  same profile or deck in-product. `docs.stripe.com` and `www.stripe.com` both resolve to
  the company `stripe.com`.
- Together is deliberately small and private — not a network to grow. Don't treat it as a
  directory or a broadcast surface.
