<!-- Connections API: OAuth, Credentials and Listing URLs · Prisma · https://prismareviews.com/docs/api-reference/connections -->
> POST, GET and DELETE /v1/connections: connect Google, Trustpilot, App Store, Google Play, Judge.me, Yelp and more to Prisma by OAuth, credentials or listing URL.

# Connections

A connection is the access a business gives Prisma to its account on one platform. Creating one imports its [locations](/docs/api-reference/locations) and starts the first review sync. There are three ways to connect, depending on the platform:

| Mode | Platforms | What you send |
| --- | --- | --- |
| `oauth` | Google Business Profile, Trustpilot | `redirect_url`; you get an `authorization_url` for the owner to approve |
| `credentials` | App Store, Google Play, Judge.me, Yotpo, REVIEWS.io, G2 | `credentials` with the platform's keys or IDs |
| `listing_url` | Yelp, Tripadvisor, Booking.com | `listing_url`, the public page of the listing |

The exact fields per platform are on [Platforms](/docs/api-reference/platforms). Prisma only connects accounts the business owns or manages, and never asks for a platform password.

## The connection object

```json
{
  "id": "con_01KJ8P7R5S3T1V9W7X5Y3Z1A2B",
  "platform": "google",
  "status": "active",
  "metadata": { "client": "acme" },
  "created_at": "2026-10-21T08:55:00.000Z",
  "updated_at": "2026-10-21T08:56:41.000Z"
}
```

| Field | Type | Description |
| --- | --- | --- |
| `id` | string | Connection ID (`con_…`). |
| `platform` | enum | Platform ID. |
| `status` | enum | `pending` (waiting for the owner to approve OAuth), `active`, `reauth_required` (the platform rejected the stored token or key) or `disconnected`. |
| `metadata` | object | Your own key-value pairs, returned as sent. |
| `created_at`, `updated_at` | timestamp | |

Credentials and tokens are never returned. They are stored encrypted (AES-256-GCM); see [Security](/security).

## Create a connection

`POST /v1/connections`

| Body param | Required | Description |
| --- | --- | --- |
| `platform` | yes | `google`, `app_store`, `google_play`, `judge_me`, `trustpilot`, `yelp`, `tripadvisor`, `booking`, `yotpo`, `reviews_io` or `g2`. |
| `redirect_url` | OAuth platforms | Where the owner lands after approving. Must be a URL. |
| `credentials` | credentials platforms, and Trustpilot | Object with the platform's fields. |
| `listing_url` | Yelp, Tripadvisor, Booking.com | Public URL of the listing. |
| `metadata` | no | Your own key-value pairs, for example your client ID. |

The response is `201` with the connection object plus extra fields that depend on the mode.

### OAuth (Google Business Profile, Trustpilot)

```bash
curl -X POST https://api.prismareviews.com/v1/connections \
  -H "Authorization: Bearer $PRISMA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"platform": "google", "redirect_url": "https://yourapp.com/prisma/callback", "metadata": {"client": "acme"}}'
```
```javascript
const res = await fetch("https://api.prismareviews.com/v1/connections", {
  method: "POST",
  headers: {
    Authorization: "Bearer " + process.env.PRISMA_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    platform: "google",
    redirect_url: "https://yourapp.com/prisma/callback",
    metadata: { client: "acme" },
  }),
});
const connection = await res.json();
// Send the business owner to connection.authorization_url
```
```python
import os
import requests

resp = requests.post(
    "https://api.prismareviews.com/v1/connections",
    json={
        "platform": "google",
        "redirect_url": "https://yourapp.com/prisma/callback",
        "metadata": {"client": "acme"},
    },
    headers={"Authorization": f"Bearer {os.environ['PRISMA_API_KEY']}"},
    timeout=30,
)
connection = resp.json()
print(connection["authorization_url"])
```

**Response `201`**

```json
{
  "id": "con_01KJ8P7R5S3T1V9W7X5Y3Z1A2B",
  "platform": "google",
  "status": "pending",
  "metadata": { "client": "acme" },
  "created_at": "2026-10-21T08:55:00.000Z",
  "updated_at": "2026-10-21T08:55:00.000Z",
  "authorization_url": "https://accounts.google.com/o/oauth2/v2/auth?client_id=...&state=..."
}
```

Send the owner of the account to `authorization_url`. They approve access on the platform, the platform sends them to Prisma, and Prisma sends them on to your `redirect_url` with these query parameters:

| Outcome | Query parameters added to `redirect_url` |
| --- | --- |
| Approved | `connection_id=con_…&status=active&locations_created=3` |
| Refused or failed | `connection_id=con_…&status=error&error=<reason>` (the platform's error, `missing_code` or `authorization_failed`) |

On success the connection becomes `active`, its locations are created and you get a `connection.updated` [webhook](/docs/api-reference/webhooks). On failure the connection becomes `disconnected`; create a new one to try again. An authorization link works once.

For Google, the account that approves must be an owner or manager of the profile; Prisma imports every location it can see. Trustpilot also needs `credentials.domain`, the domain of the Trustpilot profile, sent with the request (see [Platforms](/docs/api-reference/platforms)).

### Credentials (App Store, Google Play, Judge.me, Yotpo, REVIEWS.io, G2)

```bash
curl -X POST https://api.prismareviews.com/v1/connections \
  -H "Authorization: Bearer $PRISMA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"platform": "judge_me", "credentials": {"shop_domain": "example-store.myshopify.com", "api_token": "'"$JUDGEME_API_TOKEN"'"}}'
```
```javascript
const res = await fetch("https://api.prismareviews.com/v1/connections", {
  method: "POST",
  headers: {
    Authorization: "Bearer " + process.env.PRISMA_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    platform: "judge_me",
    credentials: {
      shop_domain: "example-store.myshopify.com",
      api_token: process.env.JUDGEME_API_TOKEN,
    },
  }),
});
console.log(res.status, await res.json());
```
```python
resp = requests.post(
    "https://api.prismareviews.com/v1/connections",
    json={
        "platform": "judge_me",
        "credentials": {
            "shop_domain": "example-store.myshopify.com",
            "api_token": os.environ["JUDGEME_API_TOKEN"],
        },
    },
    headers={"Authorization": f"Bearer {os.environ['PRISMA_API_KEY']}"},
    timeout=30,
)
print(resp.status_code, resp.json())
```

Prisma checks the shape of the credentials, then tries them against the platform before storing anything. If they work, the connection is `active` at once:

**Response `201`**

```json
{
  "id": "con_01KJ8Q0A2B4C6D8E0F2G4H6J8K",
  "platform": "judge_me",
  "status": "active",
  "metadata": {},
  "created_at": "2026-10-21T09:10:00.000Z",
  "updated_at": "2026-10-21T09:10:00.000Z",
  "locations_created": 1,
  "locations_over_plan_limit": 0
}
```

If the shape is wrong or the platform rejects them, you get `422 invalid_credentials` and nothing is stored. The `message` says which field or what the platform answered.

### Listing URL (Yelp, Tripadvisor, Booking.com)

```bash
curl -X POST https://api.prismareviews.com/v1/connections \
  -H "Authorization: Bearer $PRISMA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"platform": "yelp", "listing_url": "https://www.yelp.com/biz/example-cafe-san-francisco"}'
```
```javascript
const res = await fetch("https://api.prismareviews.com/v1/connections", {
  method: "POST",
  headers: {
    Authorization: "Bearer " + process.env.PRISMA_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    platform: "yelp",
    listing_url: "https://www.yelp.com/biz/example-cafe-san-francisco",
  }),
});
console.log(res.status, await res.json());
```
```python
resp = requests.post(
    "https://api.prismareviews.com/v1/connections",
    json={"platform": "yelp", "listing_url": "https://www.yelp.com/biz/example-cafe-san-francisco"},
    headers={"Authorization": f"Bearer {os.environ['PRISMA_API_KEY']}"},
    timeout=30,
)
print(resp.status_code, resp.json())
```

Each connection is one listing, and the response is `201` with `status: "active"`, `locations_created` and `locations_over_plan_limit`. The URL must be the public page of a listing on that platform, or you get `422 invalid_request`. Connect only listings of businesses you own or manage. These platforms are read only: Prisma reads the reviews, and each review's `url` links to where you answer it on the platform.

### With a test key

With a `pk_test_` key, any platform connects at once without credentials, OAuth or a listing URL: the connection is `active` and gets two sample locations with sample reviews. Use it to build your integration before touching a real account.

```bash
curl -X POST https://api.prismareviews.com/v1/connections \
  -H "Authorization: Bearer $PRISMA_TEST_KEY" \
  -H "Content-Type: application/json" \
  -d '{"platform": "trustpilot"}'
```

### Errors

| Status | `code` | When |
| --- | --- | --- |
| 403 | `plan_upgrade_required` | The platform isn't in your plan: Yelp, Tripadvisor, Booking.com, Yotpo, REVIEWS.io and G2 start at Beam. Includes `platform`. |
| 422 | `invalid_request` | Unknown `platform`, missing `redirect_url`, `credentials` or `listing_url` for that platform, a listing URL from another site, or a body that isn't valid JSON. |
| 422 | `invalid_credentials` | Credentials with the wrong shape, or rejected by the platform. |
| 501 | `platform_not_available` | The platform can't be connected with live keys yet. Every platform listed here is available today. |

## List connections

`GET /v1/connections`

Returns every connection of your workspace in the mode of your key, oldest first, including `pending`, `reauth_required` and `disconnected` ones. Not paginated: `next_cursor` is always `null`.

```bash
curl https://api.prismareviews.com/v1/connections \
  -H "Authorization: Bearer $PRISMA_API_KEY"
```

```json
{
  "data": [
    {
      "id": "con_01KJ8P7R5S3T1V9W7X5Y3Z1A2B",
      "platform": "google",
      "status": "active",
      "metadata": { "client": "acme" },
      "created_at": "2026-10-21T08:55:00.000Z",
      "updated_at": "2026-10-21T08:56:41.000Z"
    }
  ],
  "next_cursor": null
}
```

## Delete a connection

`DELETE /v1/connections/{id}`

```bash
curl -X DELETE https://api.prismareviews.com/v1/connections/con_01KJ8P7R5S3T1V9W7X5Y3Z1A2B \
  -H "Authorization: Bearer $PRISMA_API_KEY"
```

**Response `200`**

```json
{
  "id": "con_01KJ8P7R5S3T1V9W7X5Y3Z1A2B",
  "platform": "google",
  "status": "disconnected",
  "metadata": { "client": "acme" },
  "created_at": "2026-10-21T08:55:00.000Z",
  "updated_at": "2026-10-21T08:56:41.000Z",
  "locations_disconnected": 3
}
```

- Stored tokens and credentials are deleted immediately, and Prisma stops checking its locations.
- Its locations become `disconnected` and stop counting toward your plan. Their reviews stay readable for 30 days and are then deleted.
- `404 resource_not_found` if there is no connection with that ID in your workspace and mode.

To revoke access on the platform's side too, remove Prisma from the account's settings on that platform (for example, the connected apps of the Google account).

## When a connection needs reauthorization

If a platform rejects Prisma's token or key (the owner revoked access, a key was deleted, a token expired for good), the connection becomes `reauth_required`, Prisma stops publishing replies for it (`POST /v1/reviews/{id}/reply` returns `409 connection_reauth_required`) and you get a `connection.updated` webhook with a `reason`.

There is no endpoint to reauthorize an existing connection. Delete it and create a new one. The new connection creates new locations, with new `loc_` and `rev_` IDs, and imports the reviews again; delete the old connection first so its locations don't count toward your plan limit.
