# BentBox API — Integration Demo

A minimal, unbranded reference showing how a third-party site connects a user's
BentBox account over OAuth 2.0 and uploads a video through the API.

It's intentionally small and heavily commented so you can read it end to end and
adapt it. Everything runs server-side in plain PHP with no framework and no
database — the connection is kept in a single encrypted cookie, so it works on
one host or behind a load balancer without shared session storage.

---

## The flow

```
  index.php ──▶ connect.php ──▶  BentBox consent screen  ──▶ callback.php ──▶ upload.php
   (status)     (redirect)        (user signs in +           (exchange code    (create → sign
                                    approves access)           for tokens)        → PUT file)
```

1. **Connect** — send the user to BentBox's `/oauth/authorize` with your
   `client_id`, requested `scope`, and a random `state` (CSRF protection).
2. **Approve** — the user signs in to BentBox and approves. BentBox redirects
   back to your `redirect_uri` with a short-lived `code`.
3. **Exchange** — your server POSTs that `code` (plus your `client_secret`) to
   `/oauth/token` and receives an `access_token`, `refresh_token`, and
   `connection_id`. These are stored encrypted; the browser never sees them.
4. **Upload** — using the token you call `POST /v1/content/video` to reserve a
   `video_id`, then `POST /v1/content/upload-url` to get a presigned URL, then
   `PUT` the file bytes to that URL. The create call also declares consent
   (`sole_performer` or a `release_form_id`) and an optional `publish_on_ready`
   flag — see **Consent & publishing** below.

---

## Setup

1. **Copy the folder** into your web root so the files are reachable over HTTPS
   (OAuth and secure cookies require HTTPS).

2. **Register your redirect URI.** In your BentBox account, add the exact URL of
   this demo's `callback.php` (e.g. `https://your-domain.example/callback.php`)
   to your `redirect_uris`. It must match **character for character** — no
   trailing slash, correct host and scheme.

3. **Generate a cookie key:**
   ```
   php -r "echo base64_encode(random_bytes(32)).PHP_EOL;"
   ```

4. **Edit `config.php`** and set:
   - `BB_CLIENT_ID` / `BB_CLIENT_SECRET` — your API key and secret
   - `BB_REDIRECT_URI` — the same URL you registered in step 2
   - `BB_COOKIE_KEY` — the key from step 3 (identical on every server)
   - `BB_SCOPES` — the permissions you need (default: `upload_video,upload_photo`)

5. **Open `index.php`** in a browser and click **Connect**.

---

## Files

| File           | Role |
|----------------|------|
| `config.php`   | The only file you edit for setup: credentials, redirect URI, scopes, cookie key. |
| `bentbox.php`  | Library: HTTP helper, OAuth helpers, the encrypted-cookie token store, and the two upload API calls. |
| `partials.php` | Shared, unbranded page chrome (HTML head/footer + CSS). |
| `index.php`    | Landing page: explains the flow and shows connection status. |
| `connect.php`  | Starts OAuth (sets the `state` cookie, redirects to BentBox). |
| `callback.php` | Your `redirect_uri`: verifies `state`, exchanges the code, stores tokens, confirms. |
| `upload.php`   | Upload UI + the server-side `prepare` / `upload` / `disconnect` actions. |

---

## API reference (used here)

| Call | Purpose | Auth |
|------|---------|------|
| `GET /oauth/authorize` | Consent screen | `client_id` in the query |
| `POST /oauth/token`    | Exchange `code` (or `refresh_token`) for tokens | `client_id` + `client_secret` |
| `POST /v1/content/video` | Reserve a `video_id`, attach metadata + consent | access token + `connection_id` |
| `POST /v1/content/upload-url` | Get a presigned upload URL | access token + `connection_id` |
| `PUT <presigned url>` | Upload the file bytes | the presigned URL itself |

The access token is sent **in the request body and as an `Authorization: Bearer`
header** on the content calls, which is what the endpoints expect.

`POST /v1/content/video` also requires consent (`sole_performer` **or**
`release_form_id`) and accepts an optional `publish_on_ready` flag — see below.

---

## Consent & publishing

Every video must declare consent when its metadata is created. The demo's upload
form collects this and sends it on `POST /v1/content/video`:

- **`sole_performer`** (checkbox) — check it when the uploading creator is the
  only performer. The API stores this as `user_performer` in the video's
  `release_form` field.
- **`release_form_id`** (text) — a ProntoID release form ID covering any
  additional performer(s). Required whenever `sole_performer` is not set; the API
  rejects a create with neither (`release_required`), and the demo validates the
  same rule client- and server-side before calling the API.
- **`publish_on_ready`** (checkbox, default on) — whether BentBox publishes the
  video once processing completes, or holds it as a draft. Either way the video
  becomes publicly available only after it clears BentBox's approval review, so
  publishing here does not put unreviewed content live.

---

## Uploading the file: direct vs proxy

- **Direct (default, `BB_PROXY_UPLOAD = false`)** — the browser `PUT`s the file
  straight to the presigned storage URL. Best for large files. Requires the
  storage bucket to allow cross-origin `PUT` from your domain (CORS).
- **Proxy (`BB_PROXY_UPLOAD = true`)** — the browser sends the file to
  `upload.php`, which streams it to storage. No CORS needed and nothing
  storage-related reaches the browser, but the file passes through your server
  and is bound by PHP's `upload_max_filesize` / `post_max_size`.

---

## Notes for production

- **Token storage.** This demo keeps the connection in an encrypted cookie tied
  to the browser. In a real app you'll usually store the connection against
  *your own* logged-in user (e.g. an encrypted DB row) so it persists and can be
  used for background uploads. The `bb_store_connection` / `bb_get_connection` /
  `bb_is_connected` / `bb_clear_connection` functions are the only things to
  swap — the rest of the code is unchanged.
- **The cookie key is a secret.** Keep it out of source control where you can,
  use the same value across all instances, and rotate it if leaked (users simply
  reconnect once).
- **Token refresh** is handled: on a `403` the library refreshes with the
  `refresh_token` and retries once. Confirm the refresh grant against the current
  BentBox docs.
- **Account verification.** If the connected creator's account isn't verified,
  the upload-url step returns a `verification_required` error, which the UI
  surfaces as a failed upload.