Content and transfer REST API
Extensions and templates
A library to attach from. Nothing here is applied to a profile on its own.
List the extension library
GET/api/v1/extensions
Extensions registered for use, not extensions currently attached to anything.
Query parameters
| Field | Type | What it is |
|---|---|---|
projectId | string | Restrict to one project. |
Returns
{ total, extensions: ExtensionEntry[] }
Register an extension
POST/api/v1/extensions
Adds an unpacked extension folder to the library so profiles can attach it.
Body
| Field | Type | What it is |
|---|---|---|
namerequired | string | Display name. |
pathrequired | string | Absolute path to the unpacked folder. |
projectId | string | Owning project. |
Returns
The created ExtensionEntry.
Update an extension
PATCH/api/v1/extensions/:id
Rename it or re-point it at a different folder.
Path parameters
| Field | Type | What it is |
|---|---|---|
idrequired | string | The record’s id. |
Body
Partial<ExtensionEntry>. name, path.
Returns
The updated entry.
Remove from the library
DELETE/api/v1/extensions/:id
Removes the entry. Profiles already referencing the path keep working.
Path parameters
| Field | Type | What it is |
|---|---|---|
idrequired | string | The record’s id. |
Returns
{ deleted: true }
List presets
GET/api/v1/templates
Saved sets of profile settings used as a starting point for new profiles. A preset with a null projectId is available everywhere. Each preset describes either a desktop or a phone — read off the os in its own fingerprintOptions, never stored beside them — and applying one kind to the other produces a machine that is neither, because a phone’s screen, touch points, GPU and capability record come from a captured device record rather than the desktop catalogue.
Query parameters
| Field | Type | What it is |
|---|---|---|
projectId | string | Return only the presets usable in this project, which includes the global ones. |
kind | "desktop" | "mobile" | Only presets describing this kind of machine. Anything else is a 400 naming the field, because a filter that is silently ignored looks exactly like a filter that matched everything. |
Returns
{ total, templates: ProfileTemplate[] }
Errors
400—kindis neither "desktop" nor "mobile".
Author a preset
POST/api/v1/templates
Builds a preset from scratch: what every profile made from it starts with. Stores settings, never an identity — a preset carries the options a fingerprint is drawn from and each profile draws its own, because two profiles sharing one is two profiles a site reads as one. To learn one off a profile you already have, use POST /templates/from-profile instead. An unknown field is a 400 naming it, rather than a preset that silently does less than it was asked to.
Body
| Field | Type | What it is |
|---|---|---|
namerequired | string | Preset name. It cannot be blank, and it cannot later be emptied — a preset with no name is a row nobody can pick. |
description | string | What it is for. Shown beside the name wherever a preset is offered. |
projectId | string | null | Owning project. null makes it available in every project. |
fingerprintOptions | object | What each profile’s identity is drawn from — os, brand, timezone, languages. Never a fingerprint: every profile made from this preset draws its own, because two profiles sharing one is two profiles a site reads as one. The os here is also what decides whether the preset describes a desktop or a phone. |
privacy | PrivacyConfig | Privacy switches, as on a profile. |
startOptions | StartOptions | Launch mode and window geometry, as on a profile. |
startPages | string[] | The tabs each profile opens on launch. |
extensions | string[] | Absolute paths to unpacked extensions to attach. |
tags | string[] | Tags every profile made from this preset wears. Any name not seen before gets a colour. |
bookmarks | { title, url }[] | Bookmarks in the bar of the first window. An http:// or https:// address is required — anything else is a 400 naming the row, because a bookmark a browser cannot open is a row that does nothing. A missing title shows as the URL, which is what Chromium does. |
note | string | The profile’s note, pre-filled. Markdown — the same field the companion and the editor both edit. |
proxy | { providerId, pick } | null | A provider to mint a fresh proxy from, per profile — never an address. One gateway line mints a different session, and so a different exit, for each profile; an address stored here would put every profile the preset ever makes on one IP, which is the fault the whole provider design exists to prevent. A pasted line or an inline host is refused by name. pick is { country, state, city, minutes } in that seller’s own words, and a pick the vendor cannot spell is refused rather than dropped — a dropped token authenticates and puts the profile somewhere else without saying so. |
Returns
The created ProfileTemplate.
Errors
400—nameis blank, a field is unknown, a bookmark has no http(s) URL,proxyis an address rather than{ providerId, pick }, the named provider does not exist, or the pick names a place that seller cannot spell.
Change a preset
PATCH/api/v1/templates/:id
PATCH-shaped: an absent field is no change. proxy: null takes the provider off. There was no route for this at all — a preset could only be created and deleted, so editing one meant deleting it and rebuilding it from memory.
Path parameters
| Field | Type | What it is |
|---|---|---|
idrequired | string | The record’s id. |
Body
| Field | Type | What it is |
|---|---|---|
name | string | New name. Sending it blank is a 400 rather than a preset with no name. |
description | string | What it is for. Shown beside the name wherever a preset is offered. |
projectId | string | null | Owning project. null makes it available in every project. |
fingerprintOptions | object | What each profile’s identity is drawn from — os, brand, timezone, languages. Never a fingerprint: every profile made from this preset draws its own, because two profiles sharing one is two profiles a site reads as one. The os here is also what decides whether the preset describes a desktop or a phone. |
privacy | PrivacyConfig | Privacy switches, as on a profile. |
startOptions | StartOptions | Launch mode and window geometry, as on a profile. |
startPages | string[] | The tabs each profile opens on launch. |
extensions | string[] | Absolute paths to unpacked extensions to attach. |
tags | string[] | Tags every profile made from this preset wears. Any name not seen before gets a colour. |
bookmarks | { title, url }[] | Bookmarks in the bar of the first window. An http:// or https:// address is required — anything else is a 400 naming the row, because a bookmark a browser cannot open is a row that does nothing. A missing title shows as the URL, which is what Chromium does. |
note | string | The profile’s note, pre-filled. Markdown — the same field the companion and the editor both edit. |
proxy | { providerId, pick } | null | A provider to mint a fresh proxy from, per profile — never an address. One gateway line mints a different session, and so a different exit, for each profile; an address stored here would put every profile the preset ever makes on one IP, which is the fault the whole provider design exists to prevent. A pasted line or an inline host is refused by name. pick is { country, state, city, minutes } in that seller’s own words, and a pick the vendor cannot spell is refused rather than dropped — a dropped token authenticates and puts the profile somewhere else without saying so. |
Returns
The updated ProfileTemplate.
Errors
404— no preset with that id.400—namewas sent blank, a field is unknown, or the proxy provider or pick is one that cannot work.
Save a profile as a preset
POST/api/v1/templates/from-profile
Builds a preset out of an existing profile: its privacy switches, start options and pages, extensions, tags, bookmarks and note are copied, and its fingerprint is reduced to the options that produced it — platform, browser, timezone, languages. The identity itself is deliberately not copied, so profiles made from the preset come out of the same population without any two sharing a fingerprint. Cookies and browser data never travel. Nor does the proxy: what transfers is the provider it was minted from, if any, so every profile made from the preset mints its own session and its own exit. A pasted proxy has no provider and contributes nothing here, which is the honest outcome rather than a silent copy. To author a preset rather than learn one, use POST /templates — that is the door that takes bookmarks, a default note and a provider as things you choose.
Body
| Field | Type | What it is |
|---|---|---|
profileIdrequired | string | The profile to learn from. |
name | string | Preset name. Defaults to the profile name plus “ preset”. |
description | string | What the preset is for; shown in the chooser. |
projectId | string | null | Owning project. null makes it available in every project. Defaults to the profile’s own project. |
Returns
The created ProfileTemplate.
Errors
- 400 — profileId is missing.
- 404 — no such profile.
Delete a preset
DELETE/api/v1/templates/:id
Removes the preset. Profiles already made from it are untouched.
Path parameters
| Field | Type | What it is |
|---|---|---|
idrequired | string | The record’s id. |
Returns
{ deleted: true }
Run the API on your own profiles
The REST API and the MCP server are part of Pro: $49 a month, with the first 14 days free. Free has every browser feature and no API key.
Mosaic is a desktop app
Email yourself the link and open it on your computer.