Files
portal/docs/api_updates.md
T
NeilClack 9e9cabfb2b
Build and Push to Digital Ocean Container Registry / build-and-push (push) Successful in 1m42s
Build and Push to Digital Ocean Container Registry / migrate (push) Failing after 22s
Update docs and formatting; remove obsolete v2 schema doc
- Refresh AI guide docs (api, svelte-patterns, testing-patterns)
- Add API updates notes, drop the outdated portal_api_v2_schema.md
- Format package.json
2026-08-27 12:07:34 -05:00

331 lines
12 KiB
Markdown

# API Updates — Category Flattening, Groups, Subscription Level Removal
**Release:** v2 schema change (migration `20260821000000_flat_categories_groups_drop_subscription_levels`)
**Status:** Breaking changes. Clients must be updated.
## Summary of changes
| Endpoint | Change |
| ----------------------------------------- | ------------------------------------------------------------------------------------ |
| `GET /api/v2/categories` | **Breaking**: `parentId` removed from every record. Categories are now a flat list. |
| `GET /api/v2/groups` | **New**: returns the group list (former sub-categories). |
| `GET /api/v2/proclamations` | **Breaking**: `groupId` added; `subscriptionLevelId` removed. |
| `GET /api/v2/subscription-levels` | **Removed**: subscription levels no longer exist. |
| `POST /api/v2/license` | **Breaking**: response no longer contains `subscription_level`. |
| `POST /api/v2/automations/create/account` | **Breaking**: `subscription_level` is no longer accepted or required in the payload. |
| `POST /api/v1/license` | **Breaking**: response no longer contains `subscription_level`. |
| `POST /api/v1/automations/create/account` | **Breaking**: `subscription_level` is no longer accepted or required in the payload. |
| `GET /api/v1/categories` | Payload implicitly changed: rows no longer contain `parentId`. |
### Data model mapping
- Former **parent** categories (`Spiritual`, `Physical`, `Mental`, `Emotional`, `Financial`,
`Social`, `Biblical`, ...) became the flat **Category** list.
- Former **child** sub-categories (`General`, `Specific`, `Precise`, `Prayers`, `Scripture`)
became **Groups**.
- A proclamation's former child category becomes its `group`; its former parent category becomes
its `category`. A proclamation may move between categories without changing its group.
- Proclamations that had no sub-category (e.g. under `Custom (Client Specific)`) were assigned to
the `General` group.
- Every proclamation now has exactly one category and one group.
---
## OpenAPI 3.0 specification
```yaml
openapi: 3.0.3
info:
title: Rhemawave Portal API
version: 2.1.0
description: |
Changes in this release:
* ProclamationCategory hierarchy flattened; parentId removed everywhere.
* New ProclamationGroup resource replaces sub-categories as a movable filter.
* SubscriptionLevel resource and all level-based gating removed.
paths:
/api/v2/categories:
get:
summary: List categories (flat)
description: >
Returns all proclamation categories as a flat, ordered list.
BREAKING: the previous version returned a hierarchical list where each
record carried a nullable parentId linking children to parents. That
field no longer exists.
tags: [Categories]
responses:
'200':
description: Flat category list.
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Category'
examples:
newResponse:
summary: New response
value:
- id: 4
name: Spiritual
sortOrder: 0
- id: 2
name: Physical
sortOrder: 1
oldResponseDeprecated:
summary: Old (removed) response shape
value:
- id: 5
name: General
sortOrder: 0
parentId: 4
- id: 9
name: Specific
sortOrder: 1
parentId: 4
/api/v2/groups:
get:
summary: List groups
description: >
NEW ENDPOINT. Returns all proclamation groups ordered by sortOrder.
Groups replace the former sub-categories and act as a movable filter:
a proclamation can be moved from one category to another while keeping
its group.
tags: [Groups]
responses:
'200':
description: Group list.
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Group'
example:
- id: 1
name: General
sortOrder: 0
- id: 2
name: Specific
sortOrder: 1
/api/v2/proclamations:
get:
summary: List proclamations
description: >
Returns proclamations with their canonical frequency id and optional
color palette. BREAKING: each record now carries groupId (required,
always present) and no longer carries subscriptionLevelId. When the
optional entitlement headers are supplied, only the caller's entitled
proclamations are returned; there is no longer any per-level gating.
tags: [Proclamations]
parameters:
- in: header
name: x-license-key
required: false
schema: { type: string }
description: License key. Must be paired with x-email.
- in: header
name: x-email
required: false
schema: { type: string }
description: Account email. Must be paired with x-license-key.
responses:
'200':
description: Proclamation list.
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Proclamation'
examples:
newResponse:
summary: New response
value:
- id: b40fdcb9-703c-420e-af32-a081964c6f08
name: Peace & Relaxation
content: <p>The text content</p>
categoryId: 4
groupId: 1
solfeggioFrequencyId: 5
colorPalette:
[
'#32CD32',
'#3CB371',
'#90EE90',
'#98FB98',
'#ADFFA9',
'#C8FFD2',
'#F0FFF0'
]
oldResponseDeprecated:
summary: Old (removed) response shape
value:
- id: b40fdcb9-703c-420e-af32-a081964c6f08
name: Peace & Relaxation
content: <p>The text content</p>
categoryId: 5
solfeggioFrequencyId: 5
subscriptionLevelId: 1
'400':
description: Entitlement headers incomplete or invalid.
/api/v2/subscription-levels:
get:
summary: REMOVED
deprecated: true
description: >
This endpoint was removed. Subscription levels no longer exist in the
data model; clients must stop calling it.
tags: [Removed]
responses:
'404':
description: Route no longer exists.
/api/v2/license:
post:
summary: Validate a license key
description: >
Validates a key/email pair. BREAKING: the response no longer contains a
subscription_level object.
tags: [License]
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [license_key, email_address]
properties:
license_key: { type: string, example: ABCD-EFGH-IJKL-MNOP }
email_address: { type: string, format: email }
responses:
'200':
description: Key is valid.
content:
application/json:
schema:
$ref: '#/components/schemas/LicenseResponse'
examples:
newResponse:
summary: New response
value:
key: ABCD-EFGH-IJKL-MNOP
email_address: user@example.com
oldResponseDeprecated:
summary: Old (removed) response shape
value:
key: ABCD-EFGH-IJKL-MNOP
email_address: user@example.com
subscription_level:
id: 2
name: Advanced
description: General + Specific
'400':
description: Validation failure (missing fields, unknown key, wrong owner).
/api/v2/automations/create/account:
post:
summary: Create account + license key (GoHighLevel automation)
description: >
Creates a portal account when needed and issues a license key.
BREAKING: subscription_level was removed from the request contract. The
field is neither required nor validated anymore; sending it is ignored.
Signature headers (x-timestamp, x-nonce, x-signature) are unchanged.
tags: [Automations]
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [email]
properties:
email: { type: string, format: email }
name: { type: string }
responses:
'200':
description: Account and license key created.
'400':
description: Missing/invalid email.
'401':
description: Invalid signature.
components:
schemas:
Category:
type: object
required: [id, name, sortOrder]
properties:
id: { type: integer }
name: { type: string }
sortOrder: { type: integer }
Group:
type: object
required: [id, name, sortOrder]
properties:
id: { type: integer }
name: { type: string }
sortOrder: { type: integer }
Proclamation:
type: object
required: [id, name, content, categoryId, groupId, solfeggioFrequencyId]
properties:
id:
type: string
format: uuid
name: { type: string }
content: { type: string, description: HTML formatted content. }
categoryId:
type: integer
description: Flat category this proclamation belongs to.
groupId:
type: integer
description: >
Group membership (movable filter). Independent of categoryId;
changing the category does not change the group.
solfeggioFrequencyId:
type: integer
minimum: 1
maximum: 9
description: Canonical kiosk frequency id (not the DB autoincrement id).
colorPalette:
type: array
items: { type: string }
minItems: 7
maxItems: 7
description: Present only when a palette exists for the frequency.
LicenseResponse:
type: object
required: [key, email_address]
properties:
key: { type: string }
email_address: { type: string, format: email }
```
---
## Client migration checklist
1. **Kiosk / API consumers**
- Stop reading `parentId`; treat `/api/v2/categories` as flat.
- Fetch `/api/v2/groups` once at startup for the filter list.
- Read `groupId` from each proclamation record for filtering.
- Remove all references to `subscriptionLevelId` and `/api/v2/subscription-levels`.
- Remove `subscription_level` handling from license validation responses.
2. **GoHighLevel automation**
- Remove `subscription_level` from the account-creation webhook payload
(optional but recommended; the field is now ignored).
3. **Admin portal**
- Manage categories under Admin → Proclamation Categories (flat list, drag to reorder).
- Manage groups under Admin → Proclamation Groups (drag to reorder).
- Proclamations now select one Category and one Group independently.