# Site Requests

<Badge type="warning" text="Not yet released" />

Lets a background task call a website's API with the login of a Cowork tab on that site. When no tab is open there, Cowork opens one in the background. Cowork sends the request from that tab; no cookie, token or header ever reaches the Extension. Only the sites, methods and paths listed in `dozin.sites` are allowed.

## dozin.sites

| Field | Type | Required | Description |
|---|---|---|---|
| `host` | `string` | Yes | Lowercase host name, no scheme, port or path |
| `methods` | `string[]` | Yes | Any of `GET`, `POST`, `PUT`, `PATCH`, `DELETE` |
| `pathPrefixes` | `string[]` | Yes | 1–16 paths a request must start with |
| `minIntervalMs` | `number` | No | Least time between two requests to this host; default 1000, at most 60000 |

## ctx.site.request(request) <Badge type="warning" text="Not yet released" />

| Name | Type | Required | Description |
|---|---|---|---|
| `request.host` | `string` | Yes | A `host` from `dozin.sites` |
| `request.method` | `string` | No | Default `GET` |
| `request.path` | `string` | Yes | Starts with `/` and with one of `pathPrefixes`; no `?`, `#`, `..` |
| `request.query` | `Record<string, string \| number \| boolean>` | No | One value per key |
| `request.body` | `unknown` | No | JSON body; not allowed with `GET` |

### Returns

`Promise<{ status: number, contentType: string | null, body: unknown }>`. `body` is parsed JSON when the response is JSON.

### Errors

The promise rejects with an error whose `code` is:

| `code` | Meaning |
|---|---|
| `NEED_LOGIN` | Cowork could not open a tab on that site, or the site answered that the person is not logged in |
| `SITE_NOT_ALLOWED` | Host, method or path not in `dozin.sites` |
| `RATE_LIMITED` | The site answered 429 |
| `NETWORK_ERROR` | The request did not reach the site |
| `BAD_REQUEST` | Invalid query or body, a body with `GET`, or arguments that cannot be sent to Cowork |
| `RUN_ENDED` | The run that made the call has ended |

## ctx.site.session(host) <Badge type="warning" text="Not yet released" />

Tells whether the person seems logged in on that site.

| Name | Type | Required | Description |
|---|---|---|---|
| `host` | `string` | Yes | A `host` from `dozin.sites` |

Returns `Promise<{ loggedIn: boolean | null }>`: the result of the last request to that site when there is one; otherwise `null` when a tab on the site is open (Cowork cannot tell yet) and `false` when none is.

## Example

```js
const { loggedIn } = await ctx.site.session('welladjustedhk.janeapp.com');
if (loggedIn === false) return ctx.status('Please log in to Jane', 'warn');
try {
  const res = await ctx.site.request({ host: 'welladjustedhk.janeapp.com', path: '/admin/api/v2/locations' });
  ctx.status(`OK · HTTP ${res.status}`);
} catch (error) {
  ctx.status(error.code === 'NEED_LOGIN' ? 'Please log in to Jane' : `Error: ${error.code}`, 'error');
}
```

## Related

- [Background Tasks](https://docs.micromeet.ai/extension-sdk/service.md): Where `ctx.site` comes from
- [Overview](https://docs.micromeet.ai/extension-sdk/overview.md): The `package.json` fields
