# Mint a share link that resumes a connect flow from a server-side prefill

> create shared flow: reference page for this CustomDomain™ API operation in the sharing group. Covers parameters, request body, responses and error codes.

Source: https://docs.customdomain.ai/docs/api-reference/sharing/createSharedFlow

## `POST https://api.customdomain.ai/v1/sharing/connect`

**Forward-to-a-colleague.** The widget posts the domain(s) a teammate should connect plus an arbitrary `prefill` (the widget config to resume); the control plane stores that server-side under an opaque token and returns the absolute `link` (ends `/share/{token}`) and a `job_id`. Every domain the link targets must be one the calling token may act on: a share link never widens a domain-bound token's reach, so such a token must name a `domain` or `domains` (`400` otherwise). The link's server-side prefill is read back by `GET /share/{token}`, which the teammate's widget bootstraps from instead of a URL that carries the config in the clear. The share token EXPIRES 30 days after it is minted.

**Share by email.** With `recipient_email`, CustomDomain™ also emails the link to that address together with the DNS records the domain needs (the records of this application's connection for it when one exists, otherwise the default set) and your optional `note`. The email names the application as the product that asked. A malformed address is a `400` `invalid_request`; so is `recipient_email` without a `domain` or `domains`. Sending is capped at 3 emails per domain per application and 50 per application every 24 hours, and 10 per client IP address per hour; over any cap the call is a `429` `rate_limited` and no link is minted. When the email cannot be sent the link is still returned, with `email_error: "not_sent"`, so the widget can offer to copy it instead.

**From a server.** An API key mints a link for `application_id` (an application in the key's tenant, 404 otherwise) or for the key's own application, and the teammate's flow then connects the domain into that application. A member's key needs a role that operates apps. A widget JWT always shares for its own application.

**Whose end user the recipient is.** The recipient's widget token names the end user the sharer is, recorded when the link is made and never worked out from the domain when it is opened. A widget token shares as its own `end_user_ref` (none when it names none). An API key or an app-scoped token shares as the `end_user_ref` of the application's connection for the one domain the link names, and as no end user when there is no connection for it yet, the connection names none, or the link names several domains or none. A connection that names an end user answers only a widget token that names the same one, so this is what lets the recipient reach the connection the link was made for; another end user who shares this one's domain gets a token that names itself and is still refused on it. A `prefill` key the control plane records this in is dropped from the caller's prefill and never read back.

**What a widget token may share.** Only a domain whose connection in the application its own token owns, by the rule every managed DNS route applies: a connection that names the token's `end_user_ref`; one that names no end user when the token is bound to that domain; and, for a token that names no end user and is bound to no domain, the connection of the domain it is asked about, since it counts only that connection as its own (a token with an `end_user_ref` and no bound domain owns none that names no end user). Any other shared domain is refused with `403` `token_wrong_end_user` and no link is made. A domain with no connection yet can be shared.

**What the recipient owns and reaches.** One rule: the recipient owns exactly what the sharer owned, and may touch only the shared domains. It owns the sharer's end user and the domains the sharer's own binding made its own, recorded when the link is made, and never the shared domains it is bound to: a link made by a token that names no end user and is bound to none owns each connection by itself, so a zone that links several of the shared domains is not its own. It reaches the shared domains, intersected with the sharer's binding when the sharer was bound: an end user that is bound to no domain, sharing one of its domains, gives a token that reaches that domain and none of its others. A link made by the platform's API key or an app-scoped token owns by the end user of the connection it names (or none) and reaches the shared domains.

### Authentication

`widgetJWT`, `apiKey`

### Request body (JSON)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `application_id` | string | no | With an API key, the application the shared flow connects into (defaults to the key's own). A widget JWT may only omit it or send its own application id (403 otherwise). |
| `domain` | string | no | Single domain the teammate will connect. |
| `domains` | array of string | no | Several domains the teammate will connect. |
| `prefill` | object | no | Arbitrary widget config to resume. Served back by `GET /share/{token}`, with its `domain` and `domains` keys replaced by the normalized targets from `domain` and `domains` above. |
| `recipient_email` | string | no | Optional. One plain address (no display name, no list) to email the link and the DNS records to, for example the person who runs the domain's DNS. The instructions cover `domain`, or the first of `domains`. |
| `note` | string | no | Optional plain-text note quoted in the email (at most 280 characters; markup is shown as text, never interpreted). Ignored without `recipient_email`. |

### Responses

| Status | Description |
| --- | --- |
| `201` | Share link minted (and, with recipient_email, the email attempted) |
| `400` | Error envelope: {code, title, details}. |
| `401` | Error envelope: {code, title, details}. |
| `403` | `forbidden` (the token is bound to a different domain, or its role cannot write connections) or `token_wrong_end_user` (a widget token that does not own the connection of a domain it asks to share: the connection names another end user, or names none while the token is not bound to that domain; no link is made). |
| `404` | Error envelope: {code, title, details}. |
| `429` | Share-by-email cap reached (`rate_limited`); no link was minted. |

### `201` response body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `link` | string | yes | Absolute forwardable URL ending /share/<token>. |
| `job_id` | string | yes |  |
| `emailed_to` | string | no | Present when the email was accepted for delivery; the normalized recipient address. |
| `email_error` | `not_sent` | no | Present when recipient_email was given but the email could not be sent. The link is still valid. |

The full specification is served at `GET https://api.customdomain.ai/v1/openapi.json`.
