> ## Documentation Index
> Fetch the complete documentation index at: https://docs.revyl.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Connect accounts

> Connect a customer account to a Revyl workspace, collect its credential, and disconnect it.

Every partner API call on this page uses your **partner API key** as a bearer token, from your
servers only. The [partner API reference](/partners/api) lists each request and response in full.

<Note>
  The partner API is available to approved partners. Revyl turns it on for your platform in each
  environment and may turn on your customer accounts one at a time. Connecting an account that
  isn't turned on answers `403 partner_not_allowed`.
</Note>

```bash
export REVYL_API_BASE_URL="https://backend.revyl.ai"
export PARTNER_API_KEY="<your partner key>"
```

Prompt for your coding agent:

```text
Add Revyl partner connections to this backend.

Read https://docs.revyl.com/partners/connect.md and follow it. It's the current Revyl guide for this, so prefer it over anything you remember about Revyl.

The partner API is for approved partners. Keep the partner API key on the server, in an environment variable or this project's secret store, never in client code or a commit.

You're done when the backend can connect a test account, collect its connection credential, and disconnect it.

Ask me before anything that needs my login or approval.
```

## Connect an account

Send your own ID for the customer account, the names to show, and the email of the person
enabling the connection:

```bash
curl --request POST "${REVYL_API_BASE_URL}/api/v1/partner/connections" \
  --header "Authorization: Bearer ${PARTNER_API_KEY}" \
  --header "Content-Type: application/json" \
  --data '{
    "external_account_id": "acct_123",
    "external_account_name": "Example Workspace",
    "organization_name": "Example Workspace",
    "owner_email": "alex@example.com",
    "mode": "auto"
  }'
```

| Field | Meaning |
| --- | --- |
| `external_account_id` | Your ID for the account: 1 to 128 letters, digits, `_`, or `-`. Every later call uses it. |
| `external_account_name` | Your name for the account, shown to the person approving in Revyl. |
| `organization_name` | The name of a workspace Revyl creates. It's a display name, not an identity. Revyl may simplify it, and adds a number if the name is taken. |
| `owner_email` | The email of the person enabling the connection. Send only an address you have verified: when Revyl creates the workspace, it creates this person's Revyl account as already confirmed and makes them its Owner. |
| `mode` | `auto` (default) or `link_existing`. |

What happens depends on the mode and on whether the email already has a Revyl account:

- **`auto`, and the email has no Revyl account:** Revyl creates a workspace, makes that person
  its Owner, and answers `201` with `state: "connected"`, `origin: "provisioned"`, and the
  connection credential.
- **`auto`, and Revyl created a workspace for this account before:** Revyl reconnects that workspace
  and answers `201`, even after a disconnect.
- **`auto`, and the email already has a Revyl account:** Revyl asks for approval and answers
  `202` with `state: "awaiting_approval"`.
- **`link_existing`:** Revyl always asks for approval and answers `202`.
- **The account isn't turned on for your integration:** Revyl answers `403 partner_not_allowed`.

Connect is safe to repeat for the same account. A retry after a timeout picks up where the first
request stopped. If the account is already connected, Revyl answers `409 already_connected` with
the connection; use [Rotate the credential](#rotate-the-credential) if you lost it.

## Wait for approval

A `202` response carries an approval:

```json
{
  "connection": { "external_account_id": "acct_123", "state": "awaiting_approval" },
  "approval": {
    "user_code": "BCDF-GHJK",
    "verification_uri": "https://app.revyl.ai/connect",
    "verification_uri_complete": "https://app.revyl.ai/connect?code=…",
    "expires_in": 604800,
    "interval": 5
  }
}
```

Revyl emails the request to the person who asked. If they aren't an Owner or Admin of any of
their organizations, Revyl emails the Owners and Admins of up to three of those organizations
instead. Show the person `user_code` and a link to `verification_uri_complete`; the approver checks
that the code in Revyl matches yours. The request expires after `expires_in` seconds. Revyl sends one
reminder three days after the request if no one has decided. Calling connect again for the same
person returns the same approval and resends its email at most once every 10 minutes; a different
`owner_email` replaces the request, and the old link stops working.

Then poll every `interval` seconds:

```bash
curl --request POST \
  "${REVYL_API_BASE_URL}/api/v1/partner/connections/acct_123/approval/token" \
  --header "Authorization: Bearer ${PARTNER_API_KEY}"
```

| Response | Meaning | Next step |
| --- | --- | --- |
| `200` | Approved. The body has the connection and its credential. | Store the credential and stop polling. |
| `400 authorization_pending` | No one has decided yet. | Keep polling. |
| `400 slow_down` | You polled too fast. | Add 5 seconds to the interval. |
| `400 access_denied` | The approver declined. | Stop polling. |
| `400 expired_token` | The request expired, was replaced, or was already collected. | Connect again. |

Revyl delivers the credential once. If you stop polling before you collect it, issue one with
[Rotate the credential](#rotate-the-credential).

## Use the connection credential

The credential is an opaque API key for the connected workspace, with `expires_at` beside it.
Revyl returns it only when it's created, so store it on your servers. Use it like a Revyl API
key: send it as a bearer token to the Revyl API, or set it as `REVYL_API_KEY` for the
[CLI](/install).

```bash
REVYL_API_KEY="<connection credential>" revyl device start --platform ios --app "$APP_ID" --json
```

Work you start with it runs in the connected workspace, and the customer sees it there.

### Rotate the credential

```bash
curl --request POST \
  "${REVYL_API_BASE_URL}/api/v1/partner/connections/acct_123/credentials" \
  --header "Authorization: Bearer ${PARTNER_API_KEY}"
```

Revyl retires the current credential, then issues a new one (`201`). The credential it replaces
keeps working for a short grace period (two hours by default), so work already running on it can
finish. A credential replaced by an earlier rotation, and every session credential, stops working
at once. Rotate before `expires_at`, and after you lose a credential.

### Mint a session credential

For a short-lived runtime, such as a VM that runs one job, mint a session credential instead of
copying the connection credential:

```bash
curl --request POST \
  "${REVYL_API_BASE_URL}/api/v1/partner/connections/acct_123/session-credentials" \
  --header "Authorization: Bearer ${PARTNER_API_KEY}" \
  --header "Content-Type: application/json" \
  --data '{ "ttl_seconds": 7200 }'
```

It acts as the connection until it expires. `ttl_seconds` is 60 to 14,400 and defaults to 7,200.
The response returns `credential_id` and the secret once. A session credential also ends when
you rotate the connection credential or disconnect, and you can revoke one early with
`DELETE /api/v1/partner/connections/{external_account_id}/session-credentials/{credential_id}`.
A revoked, expired, or ended session credential answers `401`; mint a new one. A `503` means Revyl
couldn't check it; retry.

## Invite teammates

For a workspace Revyl created for the account, you can invite people as Members:

```bash
curl --request POST \
  "${REVYL_API_BASE_URL}/api/v1/partner/connections/acct_123/invitations" \
  --header "Authorization: Bearer ${PARTNER_API_KEY}" \
  --header "Content-Type: application/json" \
  --data '{ "email": "sam@example.com" }'
```

Revyl sends each address at most one invitation per UTC day. A linked organization answers
`403 not_supported_for_connection`, because its own admins invite people.

## Check and disconnect

`GET /api/v1/partner/connections/{external_account_id}` returns the account's `state`:
`connected`, `awaiting_approval`, or `not_connected`. Treat any state you don't recognize as
not usable.

To end a connection:

```bash
curl --request DELETE \
  "${REVYL_API_BASE_URL}/api/v1/partner/connections/acct_123" \
  --header "Authorization: Bearer ${PARTNER_API_KEY}"
```

Disconnecting revokes the connection's credentials and session credentials and stops every live
session started with them. App embeds in the workspace keep working until they're revoked, so
revoke yours with `DELETE /api/v1/embeds/{embed_id}` first. The workspace and its data stay with
the customer. It's safe to repeat: `204` means nothing is left to stop.

To open the workspace for a person, see [Dashboard links](/integrations/partner-dashboard).
