# API: Agent browser

| Method | Path | What it does | Scope |
|---|---|---|---|
| GET | `/v1/browser/headless` | Whether headless portal pulls can run here: the organization's switch (off until an owner turns it on) and the browser, and if not, why | `records:read` |
| PUT | `/v1/browser/headless` | Turn headless portal pulls on or off for the organization (owner, web session) (web app only) | `settings:write` |
| GET | `/v1/browser/portals` | Portal pulls and how their last run went (headless pulls say whether a sign-in is stored and when, never its value) | `records:read` |
| POST | `/v1/browser/portals` | Pull a report from a portal on a cadence, through your own signed-in browser, into a pack feed (owner) | `settings:write` |
| DELETE | `/v1/browser/portals/:id` | Delete a portal pull (owner) | `settings:write` |
| PATCH | `/v1/browser/portals/:id` | Pause, resume, run a portal pull now, or switch it between your browser and headless (owner). Run now is refused (409 sign_in_refused) after the portal refused the stored sign-in, until its maker sets it again; with a sign-in stored, only its maker can switch the mode, in the app | `settings:write` |
| DELETE | `/v1/browser/portals/:id/sign-in` | Remove a headless pull's stored sign-in and its saved browser session (its maker, an owner, from a web session) (web app only) | `settings:write` |
| PUT | `/v1/browser/portals/:id/sign-in` | Store the sign-in a headless pull uses (its maker, an owner, from a web session). Sealed; never returned: the answer says only that one is set and when (web app only) | `settings:write` |
| GET | `/v1/browser/sessions` | Your connected browsers (owners: everyone's) | `records:read` |
| POST | `/v1/browser/sessions` | The extension registers this browser for its person (agent runs they start can use it, in a tab they can see) | `records:read` |
| DELETE | `/v1/browser/sessions/:id` | Disconnect a browser (its waiting steps stop) | `records:read` |
| POST | `/v1/browser/sessions/:id/poll` | The extension asks for work: this person's next steps (at most 5; one at a time per run or pull) | `records:read` |
| POST | `/v1/browser/sessions/:id/steps/:step` | The extension answers one step (its page's text, a table, or that the page asks to sign in) | `records:read` |

## Examples

### GET /v1/browser/headless

Whether headless portal pulls can run here: the organization's switch (off until an owner turns it on) and the browser, and if not, why

```bash
curl -s "https://api.closefinch.com/v1/browser/headless" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/browser/headless`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### GET /v1/browser/portals

Portal pulls and how their last run went (headless pulls say whether a sign-in is stored and when, never its value)

```bash
curl -s "https://api.closefinch.com/v1/browser/portals" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/browser/portals`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### POST /v1/browser/portals

Pull a report from a portal on a cadence, through your own signed-in browser, into a pack feed (owner)

```bash
curl -s -X POST "https://api.closefinch.com/v1/browser/portals" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/browser/portals`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

### DELETE /v1/browser/portals/$ID

Delete a portal pull (owner)

```bash
curl -s -X DELETE "https://api.closefinch.com/v1/browser/portals/$ID" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/browser/portals/${id}`, {
  method: "DELETE",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### PATCH /v1/browser/portals/$ID

Pause, resume, run a portal pull now, or switch it between your browser and headless (owner). Run now is refused (409 sign_in_refused) after the portal refused the stored sign-in, until its maker sets it again; with a sign-in stored, only its maker can switch the mode, in the app

```bash
curl -s -X PATCH "https://api.closefinch.com/v1/browser/portals/$ID" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/browser/portals/${id}`, {
  method: "PATCH",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

### GET /v1/browser/sessions

Your connected browsers (owners: everyone's)

```bash
curl -s "https://api.closefinch.com/v1/browser/sessions" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/browser/sessions`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### POST /v1/browser/sessions

The extension registers this browser for its person (agent runs they start can use it, in a tab they can see)

```bash
curl -s -X POST "https://api.closefinch.com/v1/browser/sessions" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/browser/sessions`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

### DELETE /v1/browser/sessions/$ID

Disconnect a browser (its waiting steps stop)

```bash
curl -s -X DELETE "https://api.closefinch.com/v1/browser/sessions/$ID" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/browser/sessions/${id}`, {
  method: "DELETE",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### POST /v1/browser/sessions/$ID/poll

The extension asks for work: this person's next steps (at most 5; one at a time per run or pull)

```bash
curl -s -X POST "https://api.closefinch.com/v1/browser/sessions/$ID/poll" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/browser/sessions/${id}/poll`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

### POST /v1/browser/sessions/$ID/steps/$STEP

The extension answers one step (its page's text, a table, or that the page asks to sign in)

```bash
curl -s -X POST "https://api.closefinch.com/v1/browser/sessions/$ID/steps/$STEP" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/browser/sessions/${id}/steps/${step}`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

Request and response schemas: [https://www.closefinch.com/openapi.json](https://www.closefinch.com/openapi.json). All resources: [API reference](https://www.closefinch.com/docs/api).
