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

# Official Zapier integration API

> OAuth 2.0 and REST Hook endpoints used by the official Biqli Zapier integration.

The official Biqli Zapier integration uses OAuth 2.0 authorization code grants and Zapier REST Hook subscriptions. Each connection is scoped to one Biqli workspace.

<Warning>
  This is not a public or self-service OAuth application platform. Biqli provisions and manages one confidential OAuth client for the official Zapier integration. Biqli users do not create OAuth applications, handle client credentials, or choose scopes.
</Warning>

When a user selects **Connect Biqli** in Zapier, Zapier redirects them to Biqli. The user signs in, selects a workspace, and approves the fixed permissions requested by the integration. Biqli then returns the user to Zapier. The endpoint details below are provided for integration transparency, support, and Zapier review; they are not end-user setup steps.

## OAuth configuration

| Purpose                    | Method | URL                                  |
| :------------------------- | :----- | :----------------------------------- |
| Authorization              | `GET`  | `https://biq.li/oauth/authorize`     |
| Token exchange and refresh | `POST` | `https://biq.li/api/v1/oauth/token`  |
| Token revocation           | `POST` | `https://biq.li/api/v1/oauth/revoke` |
| Connection test            | `GET`  | `https://biq.li/api/v1/oauth/me`     |

The authorization request uses these parameters:

| Parameter       | Required | Description                                                                 |
| :-------------- | :------- | :-------------------------------------------------------------------------- |
| `client_id`     | Yes      | Identifier for the official Zapier OAuth client managed by Biqli and Zapier |
| `redirect_uri`  | Yes      | Exact registered Zapier callback URL                                        |
| `response_type` | Yes      | Must be `code`                                                              |
| `state`         | Yes      | Opaque value generated and verified by Zapier                               |
| `scope`         | Yes      | Fixed, space-separated permissions requested by the official integration    |

Biqli asks the signed-in user to select a workspace and approve the requested access. The user must own that workspace or have permission to create webhooks in it. Biqli then redirects to the registered callback with `code` and the unchanged `state`.

### Permissions requested by Zapier

The official integration always requests these permissions. Users approve them as a set; they do not configure the scope list themselves.

| Scope            | Access                                         |
| :--------------- | :--------------------------------------------- |
| `workspace.read` | Read the connected user and workspace identity |
| `webhooks.read`  | Read sample webhook event payloads             |
| `webhooks.write` | Create and remove Zapier webhook subscriptions |

## Authorization-code exchange

After approval, Zapier exchanges the single-use authorization code through a form-encoded server-to-server request. The confidential client credentials never pass through the user's browser.

```bash theme={null}
curl --request POST \
  --url https://biq.li/api/v1/oauth/token \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'grant_type=authorization_code' \
  --data-urlencode 'client_id=YOUR_CLIENT_ID' \
  --data-urlencode 'client_secret=YOUR_CLIENT_SECRET' \
  --data-urlencode 'code=AUTHORIZATION_CODE' \
  --data-urlencode 'redirect_uri=YOUR_REGISTERED_REDIRECT_URI'
```

Successful exchanges return a bearer access token, a rotating refresh token, the access-token lifetime, and the granted scopes:

```json theme={null}
{
  "token_type": "Bearer",
  "access_token": "REDACTED",
  "expires_in": 3600,
  "refresh_token": "REDACTED",
  "scope": "workspace.read webhooks.read webhooks.write"
}
```

Authorization codes are single-use and expire after five minutes. Access tokens expire after one hour by default.

## Automatic token refresh

Zapier automatically exchanges the stored refresh token when an access token expires. This request is server-to-server and requires no user action.

```bash theme={null}
curl --request POST \
  --url https://biq.li/api/v1/oauth/token \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'grant_type=refresh_token' \
  --data-urlencode 'client_id=YOUR_CLIENT_ID' \
  --data-urlencode 'client_secret=YOUR_CLIENT_SECRET' \
  --data-urlencode 'refresh_token=YOUR_REFRESH_TOKEN'
```

Every successful refresh returns a new access token and a new refresh token. Zapier replaces both stored values. Reusing the previous refresh token revokes the connection and its Zapier webhook subscriptions.

## Connection revocation

The integration can revoke a connection with either its current access token or refresh token:

```bash theme={null}
curl --request POST \
  --url https://biq.li/api/v1/oauth/revoke \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'client_id=YOUR_CLIENT_ID' \
  --data-urlencode 'client_secret=YOUR_CLIENT_SECRET' \
  --data-urlencode 'token=TOKEN_TO_REVOKE'
```

Revocation deletes the connection's Zapier webhook subscriptions and invalidates its access token. The endpoint returns an empty JSON object even when the token is already invalid.

## Test the connection

```bash theme={null}
curl --request GET \
  --url https://biq.li/api/v1/oauth/me \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer $ACCESS_TOKEN"
```

```json theme={null}
{
  "id": "01M34EXAMPLECONNECTION00000",
  "user_id": "123",
  "user_name": "Jane Doe",
  "workspace_id": "biq_ws_01M34EXAMPLE00000000000",
  "workspace_name": "Example workspace",
  "workspace": {
    "id": "biq_ws_01M34EXAMPLE00000000000",
    "name": "Example workspace"
  }
}
```

## Create a REST Hook subscription

Zapier sends its unique `bundle.targetUrl` and the event handled by the trigger.

```bash theme={null}
curl --request POST \
  --url https://biq.li/api/v1/integrations/zapier/webhooks \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --header "Authorization: Bearer $ACCESS_TOKEN" \
  --data '{
    "target_url": "https://hooks.zapier.com/hooks/standard/example/",
    "event": "link.created"
  }'
```

```json theme={null}
{
  "id": "wh_01M34EXAMPLE000000000000",
  "event": "link.created"
}
```

Biqli validates that the target is a public HTTP or HTTPS destination. Private, loopback, link-local, reserved, credential-bearing, and unsafe redirect targets are rejected. A target URL can have only one subscription in a workspace.

The supported event values are:

* `link.created`
* `link.updated`
* `link.deleted`
* `link.clicked`
* `lead.created`
* `sale.created`

See [Webhook event types](/webhooks/event-types) for every payload contract. Deliveries use the retry behavior documented in [Delivery attempts and retries](/webhooks/delivery-retries).

## Remove a REST Hook subscription

Use the `id` returned when the subscription was created:

```bash theme={null}
curl --request DELETE \
  --url https://biq.li/api/v1/integrations/zapier/webhooks/wh_01M34EXAMPLE000000000000 \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer $ACCESS_TOKEN"
```

```json theme={null}
{
  "id": "wh_01M34EXAMPLE000000000000"
}
```

Deletion is scoped to the authenticated OAuth connection and is idempotent.

## Load sample trigger data

Zapier uses the sample endpoint while a user configures a trigger. Replace `{event}` with one supported event value.

```bash theme={null}
curl --request GET \
  --url https://biq.li/api/v1/integrations/zapier/events/link.created/sample \
  --header 'Accept: application/json' \
  --header "Authorization: Bearer $ACCESS_TOKEN"
```

The response is an array containing one representative webhook envelope:

```json theme={null}
[
  {
    "id": "evt_01M34EXAMPLE000000000000",
    "event": "link.created",
    "createdAt": "2026-09-22T12:00:00+00:00",
    "data": {
      "id": "biq_lnk_01M34EXAMPLE00000000000",
      "url": "https://example.com/products/new",
      "shortUrl": "https://biq.li/example",
      "key": "example",
      "workspaceId": "biq_ws_01M34EXAMPLE00000000000"
    }
  }
]
```

## Errors

| Status | Meaning                                                      |
| :----- | :----------------------------------------------------------- |
| `400`  | Invalid OAuth request, client, redirect URI, grant, or scope |
| `401`  | Missing, expired, revoked, or invalid credentials            |
| `403`  | Missing scope, workspace access, or webhook permission       |
| `404`  | Unsupported event or unavailable resource                    |
| `422`  | Invalid subscription payload or duplicate target URL         |
| `429`  | Request rate limit exceeded                                  |

OAuth errors return `error` and `error_description`. Validation errors return the standard Biqli validation response.
