# 04. API reference (blogger_api)

Base: `https://api.blogger.mytown.ink`

## Health
### GET /ping.php
Returns `{ "ok": true, "time": "ISO-8601" }`.

## Checkout
### POST /checkout/create.php
Creates a Yoco checkout and provisions a tenant folder.

**Request JSON**
- `email` (required)
- `amount_cents` (optional, defaults to `config.php['price_cents']`)
- `currency` (optional, default `ZAR`)

**Response JSON**
- `ok` boolean
- `tenant_ref`
- `checkoutId`
- `redirectUrl`
- `successUrl`

## Webhooks
### POST /webhooks/yoco.php
Validates signature (Svix style headers), confirms checkout status via Yoco API, activates tenant.

**Important headers**
- `webhook-id` / `svix-id`
- `webhook-timestamp` / `svix-timestamp`
- `webhook-signature` / `svix-signature`

**Behavior**
- Writes `tenants/{ref}/.env` (if missing fields)
- Writes `tenants/{ref}/active.json` with download token

Returns `{ ok: true, tenant_ref }` on success.

## Kit delivery
### POST /kit/package.php
Streams the protected tarball if tenant is active and license matches.

**Request JSON**
- `ref`
- `license`

**Response**
- `200` with `application/gzip` body (tar.gz)

## WordPress
### POST /wp/connect.php
Stores WordPress connection details for a tenant.

**Request JSON**
- `ref`
- `license`
- `wp_url`
- `wp_user`
- `wp_app_password` (stored encrypted server-side)

**Response JSON**
- `ok`, `wp_connected`, echoes `wp_url` and `wp_user`

### POST /wp/test_post.php
Creates a draft test post via WP REST using stored credentials.

**Request JSON**
- `ref`
- `license`

**Response JSON**
- `ok`
- `post_id`
- `link` (WordPress canonical link if returned)
- `preview_url`
- `edit_url` (admin edit link)

## Content workflow (Option 2)
### POST /content/generate.php
Generates draft content by invoking the tenant's stored OpenAI key, persists it under `tenants/{ref}/drafts/{draft_id}.json`, and returns the preview / approve tokens. The call returns a clear error if no OpenAI key has been saved yet.

**Request JSON**
- `ref` (required tenant reference, `t_{hex}`)
- `topic` or `prompt` (one is required)
- `title` (optional override of the generated headline)

**Response JSON**
- `ok`
- `draft_id`
- `status` (`generated`)
- `preview_token`
- `approve_token`
- `preview_path` (relative `GET /content/preview.php?ref=...&draft=...&token=...`)
- `approve_path` (relative path for `POST /content/approve.php`)

### GET /content/preview.php
Renders the stored draft HTML inside a hardened shell, showing the plaintext excerpt and social snippets as part of a review view.

**Query parameters**
- `ref`
- `draft`
- `token`

Preview tokens expire after `PREVIEW_TOKEN_TTL_SECS` (default `604800` seconds / 7 days) measured from the draft creation time; expired or invalid tokens are rejected with HTTP `403`.

### POST /content/approve.php
Uses the stored WordPress credentials (`tenants/{ref}/data/wp.json`) to publish the draft, captures `wp_post_id`/`wp_link`, and transitions the draft to `published`. Only the approve token may trigger this action.

**Request JSON**
- `ref`
- `draft`
- `token`

Approve tokens expire after `APPROVE_TOKEN_TTL_SECS` (default `604800` seconds / 7 days). The endpoint is single-use and idempotent: once publishing succeeds it invalidates the token and subsequent calls return the stored `wp_post_id`/`wp_link` without publishing again, while missing/expired/invalid tokens return HTTP `403`.

**Response JSON**
- `ok`
- `draft_id`
- `wp_post_id`
- `wp_link`
- `status` (`published`)

## OpenAI key management
### POST /openai/save.php
Stores the provided OpenAI API key encrypted per tenant. Requires `ref` and `api_key` in the JSON body.

### POST /openai/test.php
Validates the tenant's saved key by decrypting it and performing a minimal OpenAI request. Returns `{ ok: true, message: "ok" }` on success.

### POST /openai/delete.php
Deletes the tenant's stored OpenAI key (useful for rotation or cleanup).

## Option 2 roadmap
- Capture and encrypt each tenant's OpenAI key (`POST /openai/save.php`, stored at `tenants/{ref}/data/openai.json`).
- Verify keys via `POST /openai/test.php`, then generate drafts (`POST /content/generate.php`) and notify customers.
- Ensure observability around the new content endpoints and rotate tokens before flipping the workflow live.

## Social add-ons (LinkedIn + Facebook)
### POST /social/connect.php
Stores an encrypted token payload for the requested provider (`linkedin` or `facebook`) using `WP_MASTER_KEY_B64`. Saved files live at `tenants/{ref}/data/social/{provider}.json`.

### POST /social/queue_post.php
Appends a JSON line to `tenants/{ref}/queue/jobs.jsonl` describing `provider`, `draft_id`, and arbitrary `payload`. Jobs are created with a `status` of `queued`.

### GET /social/status.php
Returns the connected provider map plus the last queued job (`provider`, `draft_id`, `status`, `created_at`).
