@growthub/cli 0.3.56 → 0.3.58
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/worker-kits/growthub-zernio-social-v1/QUICKSTART.md +209 -0
- package/assets/worker-kits/growthub-zernio-social-v1/brands/NEW-CLIENT.md +74 -0
- package/assets/worker-kits/growthub-zernio-social-v1/brands/_template/brand-kit.md +131 -0
- package/assets/worker-kits/growthub-zernio-social-v1/brands/growthub/brand-kit.md +141 -0
- package/assets/worker-kits/growthub-zernio-social-v1/bundles/growthub-zernio-social-v1.json +55 -0
- package/assets/worker-kits/growthub-zernio-social-v1/docs/ai-caption-layer.md +132 -0
- package/assets/worker-kits/growthub-zernio-social-v1/docs/local-adapters.md +123 -0
- package/assets/worker-kits/growthub-zernio-social-v1/docs/platform-coverage.md +112 -0
- package/assets/worker-kits/growthub-zernio-social-v1/docs/postiz-ui-shell-integration.md +166 -0
- package/assets/worker-kits/growthub-zernio-social-v1/docs/posts-and-queues-layer.md +208 -0
- package/assets/worker-kits/growthub-zernio-social-v1/docs/zernio-api-integration.md +265 -0
- package/assets/worker-kits/growthub-zernio-social-v1/examples/analytics-brief-sample.md +97 -0
- package/assets/worker-kits/growthub-zernio-social-v1/examples/client-proposal-sample.md +106 -0
- package/assets/worker-kits/growthub-zernio-social-v1/examples/content-calendar-sample.md +74 -0
- package/assets/worker-kits/growthub-zernio-social-v1/examples/social-campaign-sample.md +105 -0
- package/assets/worker-kits/growthub-zernio-social-v1/growthub-meta/README.md +146 -0
- package/assets/worker-kits/growthub-zernio-social-v1/growthub-meta/kit-standard.md +120 -0
- package/assets/worker-kits/growthub-zernio-social-v1/kit.json +104 -0
- package/assets/worker-kits/growthub-zernio-social-v1/output/README.md +63 -0
- package/assets/worker-kits/growthub-zernio-social-v1/output-standards.md +132 -0
- package/assets/worker-kits/growthub-zernio-social-v1/runtime-assumptions.md +170 -0
- package/assets/worker-kits/growthub-zernio-social-v1/setup/check-deps.mjs +117 -0
- package/assets/worker-kits/growthub-zernio-social-v1/setup/check-deps.sh +86 -0
- package/assets/worker-kits/growthub-zernio-social-v1/setup/install-mcp.mjs +177 -0
- package/assets/worker-kits/growthub-zernio-social-v1/setup/setup.mjs +247 -0
- package/assets/worker-kits/growthub-zernio-social-v1/setup/verify-env.mjs +138 -0
- package/assets/worker-kits/growthub-zernio-social-v1/skills.md +332 -0
- package/assets/worker-kits/growthub-zernio-social-v1/templates/analytics-brief.md +101 -0
- package/assets/worker-kits/growthub-zernio-social-v1/templates/caption-copy-deck.md +105 -0
- package/assets/worker-kits/growthub-zernio-social-v1/templates/client-proposal.md +98 -0
- package/assets/worker-kits/growthub-zernio-social-v1/templates/content-calendar.md +70 -0
- package/assets/worker-kits/growthub-zernio-social-v1/templates/platform-publishing-plan.md +86 -0
- package/assets/worker-kits/growthub-zernio-social-v1/templates/scheduling-manifest.md +92 -0
- package/assets/worker-kits/growthub-zernio-social-v1/templates/social-campaign-brief.md +102 -0
- package/assets/worker-kits/growthub-zernio-social-v1/validation-checklist.md +85 -0
- package/assets/worker-kits/growthub-zernio-social-v1/workers/zernio-social-operator/CLAUDE.md +307 -0
- package/package.json +1 -1
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# Posts + Queues Layer
|
|
2
|
+
|
|
3
|
+
This document specifies the JSON shapes the operator must produce. Every shape is a valid request body for the corresponding Zernio REST endpoint, so manifests can be piped directly into `curl` or the Zernio SDKs with no re-shaping.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Scheduling Manifest
|
|
8
|
+
|
|
9
|
+
The scheduling manifest is the machine-readable record the operator writes to `output/<client-slug>/<project-slug>/scheduling-manifest.json` whenever scheduling is requested.
|
|
10
|
+
|
|
11
|
+
### Top-level shape
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{
|
|
15
|
+
"zernioSchedulingManifest": {
|
|
16
|
+
"version": "1.0",
|
|
17
|
+
"profileId": "<ZERNIO_PROFILE_ID>",
|
|
18
|
+
"timezone": "America/New_York",
|
|
19
|
+
"dryRun": false,
|
|
20
|
+
"generatedAt": "2026-04-15T14:30:00-04:00",
|
|
21
|
+
"notes": "<free-form operator notes — kept with the manifest>",
|
|
22
|
+
"posts": [ /* post entries */ ]
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
| Field | Required | Type | Notes |
|
|
28
|
+
|---|---|---|---|
|
|
29
|
+
| `version` | Yes | string | Manifest schema version. Current: `"1.0"`. |
|
|
30
|
+
| `profileId` | Yes | string | Must be a real Zernio profile id in api-live mode. In agent-only mode may be `"placeholder"` provided `dryRun: true`. |
|
|
31
|
+
| `timezone` | Yes | string | IANA name. Default: value of `ZERNIO_TIMEZONE` or the profile's default. |
|
|
32
|
+
| `dryRun` | Yes | boolean | `true` in agent-only mode. `false` in api-live and hybrid modes. |
|
|
33
|
+
| `generatedAt` | Yes | string | ISO 8601 with tz offset. |
|
|
34
|
+
| `notes` | No | string | Free-form notes — kept with the manifest for audit. |
|
|
35
|
+
| `posts` | Yes | array | 1..N entries. |
|
|
36
|
+
|
|
37
|
+
### Per-post entry shape
|
|
38
|
+
|
|
39
|
+
Each entry is a direct body for `POST /api/v1/posts`, with two additional fields the operator uses for bookkeeping (`clientPostId`, `status`).
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"clientPostId": "urban-cycle-20260501-001",
|
|
44
|
+
"content": "Launch day — shipping our spring gravel lineup. Ride it today →",
|
|
45
|
+
"scheduledFor": "2026-05-01T09:00:00-04:00",
|
|
46
|
+
"timezone": "America/New_York",
|
|
47
|
+
"media": [{ "mediaId": "med_HERO_01" }],
|
|
48
|
+
"platforms": [
|
|
49
|
+
{ "platform": "instagram", "accountId": "acc_ig_UrbanCycle" },
|
|
50
|
+
{ "platform": "twitter", "accountId": "acc_x_UrbanCycle" }
|
|
51
|
+
],
|
|
52
|
+
"status": "pending"
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
| Field | Required | Type | Notes |
|
|
57
|
+
|---|---|---|---|
|
|
58
|
+
| `clientPostId` | Yes | string | Operator-generated id. Format: `<client-slug>-<YYYYMMDD>-<sequence>`. Used as the `Idempotency-Key` when submitting to Zernio. Not sent in the body. |
|
|
59
|
+
| `content` | Yes | string | The selected caption variant. |
|
|
60
|
+
| `scheduledFor` | Conditional | string | ISO 8601 with tz offset. Required unless the post is attached to a queue via `queueId`. |
|
|
61
|
+
| `timezone` | Yes | string | IANA name. |
|
|
62
|
+
| `media` | No | array | Array of `{ "mediaId": "<id>" }`. In api-live mode must reference real Zernio `mediaId` values obtained from `POST /api/v1/media`. |
|
|
63
|
+
| `platforms` | Yes | array | 1..N `{ platform, accountId }`. Every `platform` must exist in `docs/platform-coverage.md`. |
|
|
64
|
+
| `queueId` | Conditional | string | Only when the post is attached to a queue. Mutually exclusive with `scheduledFor`. |
|
|
65
|
+
| `status` | Yes | string | Operator bookkeeping. Always starts at `"pending"` and transitions to `"scheduled"` / `"published"` / `"failed"` once Zernio confirms. |
|
|
66
|
+
|
|
67
|
+
### Submitting a manifest
|
|
68
|
+
|
|
69
|
+
Each entry becomes one Zernio POST:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
curl -sS -X POST \
|
|
73
|
+
"${ZERNIO_API_URL:-https://zernio.com/api/v1}/posts" \
|
|
74
|
+
-H "Authorization: Bearer ${ZERNIO_API_KEY}" \
|
|
75
|
+
-H "Content-Type: application/json" \
|
|
76
|
+
-H "Idempotency-Key: <clientPostId>" \
|
|
77
|
+
--data-binary @- <<'JSON'
|
|
78
|
+
{
|
|
79
|
+
"profileId": "prof_abc123",
|
|
80
|
+
"content": "...",
|
|
81
|
+
"scheduledFor": "2026-05-01T09:00:00-04:00",
|
|
82
|
+
"timezone": "America/New_York",
|
|
83
|
+
"media": [{ "mediaId": "med_HERO_01" }],
|
|
84
|
+
"platforms": [{ "platform": "twitter", "accountId": "acc_x_111" }]
|
|
85
|
+
}
|
|
86
|
+
JSON
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The operator is responsible for issuing one request per `posts[]` entry and for retrying on 429/5xx with the same `Idempotency-Key`.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Recurring Queue Definition
|
|
94
|
+
|
|
95
|
+
Queues define a repeating schedule on a profile. Posts attached to a queue auto-schedule into the next available slot.
|
|
96
|
+
|
|
97
|
+
### Queue shape
|
|
98
|
+
|
|
99
|
+
Body of `POST /api/v1/queues` and `PUT /api/v1/queues/<queueId>`:
|
|
100
|
+
|
|
101
|
+
```json
|
|
102
|
+
{
|
|
103
|
+
"profileId": "prof_abc123",
|
|
104
|
+
"name": "weekly-evergreen",
|
|
105
|
+
"timezone": "America/New_York",
|
|
106
|
+
"slots": [
|
|
107
|
+
{ "day": "mon", "time": "09:00", "platforms": ["twitter", "linkedin"] },
|
|
108
|
+
{ "day": "wed", "time": "12:30", "platforms": ["instagram"] },
|
|
109
|
+
{ "day": "fri", "time": "17:00", "platforms": ["bluesky", "threads"] }
|
|
110
|
+
]
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
| Field | Required | Type | Notes |
|
|
115
|
+
|---|---|---|---|
|
|
116
|
+
| `profileId` | Yes | string | Zernio profile owning the queue. |
|
|
117
|
+
| `name` | Yes | string | Lowercase kebab-case recommended. |
|
|
118
|
+
| `timezone` | Yes | string | IANA name. |
|
|
119
|
+
| `slots` | Yes | array | 1..N slots. |
|
|
120
|
+
| `slots[].day` | Yes | string | One of `mon|tue|wed|thu|fri|sat|sun`. |
|
|
121
|
+
| `slots[].time` | Yes | string | `HH:MM` 24-hour. |
|
|
122
|
+
| `slots[].platforms` | Yes | array | Platforms enabled for this slot. |
|
|
123
|
+
|
|
124
|
+
### Post attached to a queue
|
|
125
|
+
|
|
126
|
+
```json
|
|
127
|
+
{
|
|
128
|
+
"profileId": "prof_abc123",
|
|
129
|
+
"queueId": "que_xyz789",
|
|
130
|
+
"content": "Weekend builder log: three wins, one lesson.",
|
|
131
|
+
"platforms": [{ "platform": "twitter", "accountId": "acc_x_111" }]
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
The request is still `POST /api/v1/posts` but with `queueId` instead of `scheduledFor`. Zernio returns the computed `scheduledFor` in the response.
|
|
136
|
+
|
|
137
|
+
### Queue deliverable in the kit
|
|
138
|
+
|
|
139
|
+
The operator writes a queue definition alongside the scheduling manifest as:
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
output/<client-slug>/<project-slug>/queue-<queue-name>.json
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The file contains one JSON object — the `zernioQueue` wrapper below — so that it reads as documentation plus a ready-to-submit request body.
|
|
146
|
+
|
|
147
|
+
```json
|
|
148
|
+
{
|
|
149
|
+
"zernioQueue": {
|
|
150
|
+
"version": "1.0",
|
|
151
|
+
"profileId": "<ZERNIO_PROFILE_ID>",
|
|
152
|
+
"dryRun": false,
|
|
153
|
+
"queue": {
|
|
154
|
+
"profileId": "<ZERNIO_PROFILE_ID>",
|
|
155
|
+
"name": "weekly-evergreen",
|
|
156
|
+
"timezone": "America/New_York",
|
|
157
|
+
"slots": [
|
|
158
|
+
{ "day": "mon", "time": "09:00", "platforms": ["twitter", "linkedin"] }
|
|
159
|
+
]
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Media Upload
|
|
168
|
+
|
|
169
|
+
Every image or video referenced by a post must be uploaded first.
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
curl -sS -X POST \
|
|
173
|
+
"${ZERNIO_API_URL:-https://zernio.com/api/v1}/media" \
|
|
174
|
+
-H "Authorization: Bearer ${ZERNIO_API_KEY}" \
|
|
175
|
+
-H "Idempotency-Key: media-urban-cycle-20260501-hero-01" \
|
|
176
|
+
-F "file=@./media/urban-cycle/hero-01.png" \
|
|
177
|
+
-F "profileId=prof_abc123"
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
The response includes `mediaId`. That id is what the scheduling manifest references.
|
|
181
|
+
|
|
182
|
+
In `agent-only` mode the operator emits placeholder `mediaId` values prefixed with `placeholder_` and documents the required asset in the Caption Copy Deck's "Media Notes" column. The user uploads the real media and replaces placeholders before submitting.
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Idempotency Contract
|
|
187
|
+
|
|
188
|
+
| Endpoint | Idempotency key source |
|
|
189
|
+
|---|---|
|
|
190
|
+
| `POST /api/v1/posts` | `clientPostId` from the manifest entry |
|
|
191
|
+
| `POST /api/v1/queues` | `queue.name` prefixed with `queue-` |
|
|
192
|
+
| `POST /api/v1/media` | `media-<client-slug>-<YYYYMMDD>-<asset-slug>` |
|
|
193
|
+
|
|
194
|
+
The operator must NEVER send different bodies under the same `Idempotency-Key`. If content changes, increment the manifest version and use a new key.
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Validation Rules (pre-submission)
|
|
199
|
+
|
|
200
|
+
Before any submission, re-run through `validation-checklist.md`. Specifically:
|
|
201
|
+
|
|
202
|
+
- Every `posts[].platforms[].platform` exists in `docs/platform-coverage.md`
|
|
203
|
+
- Every `clientPostId` matches the filename conventions in `output-standards.md`
|
|
204
|
+
- `scheduledFor` timestamps all fall inside the campaign window from the Social Campaign Brief
|
|
205
|
+
- `dryRun` matches the declared execution mode
|
|
206
|
+
- No post entry exceeds per-platform character limits from `docs/ai-caption-layer.md`
|
|
207
|
+
|
|
208
|
+
Failure on any of these is a blocker — fix the manifest before submitting.
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
# Zernio API Integration
|
|
2
|
+
|
|
3
|
+
This document is the reference contract between the `growthub-zernio-social-v1` kit and the [Zernio](https://zernio.com) REST API. It is frozen at kit creation and should be updated when the upstream API contract changes.
|
|
4
|
+
|
|
5
|
+
> Source of truth upstream: [docs.zernio.com](https://docs.zernio.com). When this document conflicts with live Zernio docs, the live docs win; update this file and the kit version.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Base Contract
|
|
10
|
+
|
|
11
|
+
| Field | Value |
|
|
12
|
+
|---|---|
|
|
13
|
+
| Base URL | `https://zernio.com/api/v1` |
|
|
14
|
+
| Env var | `ZERNIO_API_URL` (override only for regional / proxy deployments) |
|
|
15
|
+
| Transport | HTTPS only |
|
|
16
|
+
| Request content type | `application/json` (JSON endpoints) · `multipart/form-data` (`/media` upload) |
|
|
17
|
+
| Response content type | `application/json` |
|
|
18
|
+
| Character encoding | UTF-8 |
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Authentication
|
|
23
|
+
|
|
24
|
+
Every request carries a single bearer header:
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
Authorization: Bearer ${ZERNIO_API_KEY}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Key format
|
|
31
|
+
|
|
32
|
+
- Prefix: `sk_`
|
|
33
|
+
- Body: 64 hex characters
|
|
34
|
+
- Total length: 67 characters
|
|
35
|
+
|
|
36
|
+
Regex: `^sk_[0-9a-fA-F]{64}$`
|
|
37
|
+
|
|
38
|
+
### Key scopes
|
|
39
|
+
|
|
40
|
+
| Scope | Purpose |
|
|
41
|
+
|---|---|
|
|
42
|
+
| `read` | Read-only endpoints only (profiles, accounts, analytics, inbox listing) |
|
|
43
|
+
| `read-write` | Everything in `read` plus create/update posts, queues, media, and inbox replies |
|
|
44
|
+
|
|
45
|
+
### Key scope filter
|
|
46
|
+
|
|
47
|
+
An individual key may be scoped `full` (any profile on the account) or `profiles-specific` (restricted to a list of profile IDs).
|
|
48
|
+
|
|
49
|
+
### Idempotency
|
|
50
|
+
|
|
51
|
+
Attach an `Idempotency-Key` header to every write request. The operator uses the `clientPostId` from the scheduling manifest as the idempotency key so the manifest can be re-submitted safely.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Core Resource Model
|
|
56
|
+
|
|
57
|
+
Zernio models social publishing around five primary resources:
|
|
58
|
+
|
|
59
|
+
| Resource | Endpoint root | Role |
|
|
60
|
+
|---|---|---|
|
|
61
|
+
| Profiles | `/api/v1/profiles` | A container that groups social accounts. Every request is implicitly scoped to one profile for scheduling. |
|
|
62
|
+
| Accounts | `/api/v1/accounts` | A connected social account that belongs to a profile. Identified by `accountId`. |
|
|
63
|
+
| Posts | `/api/v1/posts` | Schedulable content. One post can fan out to many `{ platform, accountId }` pairs. |
|
|
64
|
+
| Queues | `/api/v1/queues` | Recurring time-slot schedule attached to a profile. Posts added to a queue auto-schedule into the next open slot. |
|
|
65
|
+
| Media | `/api/v1/media` | Image, video, and document assets uploaded once and referenced by `mediaId` from a post body. |
|
|
66
|
+
|
|
67
|
+
Two secondary resources:
|
|
68
|
+
|
|
69
|
+
| Resource | Endpoint root | Role |
|
|
70
|
+
|---|---|---|
|
|
71
|
+
| Inbox | `/api/v1/inbox` | Unified DM, comment, and review conversations aggregated per profile. |
|
|
72
|
+
| Analytics | `/api/v1/analytics` | Per-post and per-account metrics. |
|
|
73
|
+
|
|
74
|
+
Supporting endpoints:
|
|
75
|
+
|
|
76
|
+
| Endpoint | Role |
|
|
77
|
+
|---|---|
|
|
78
|
+
| `/api/v1/api-keys` | Create, list, rotate, and revoke API keys |
|
|
79
|
+
| `/api/v1/connect/<platform>` | Begin platform OAuth / credential flow for a new account on a profile |
|
|
80
|
+
| `/api/v1/platforms` | Live list of supported platforms and their per-platform capability flags |
|
|
81
|
+
|
|
82
|
+
Extended capability surface (confirmed in `zernio-cli`, may be plan-gated):
|
|
83
|
+
|
|
84
|
+
| Resource | Endpoint root | Role |
|
|
85
|
+
|---|---|---|
|
|
86
|
+
| Contacts | `/api/v1/contacts` | CRUD + bulk create + custom fields |
|
|
87
|
+
| Broadcasts | `/api/v1/broadcasts` | Create / schedule / send / cancel + recipient management |
|
|
88
|
+
| Sequences | `/api/v1/sequences` | Create / activate / pause + enrollment management |
|
|
89
|
+
| Automations | `/api/v1/automations` | Create / run / inspect execution logs |
|
|
90
|
+
| Webhooks | `/api/v1/webhooks` | Settings (create/update) + logs + signature verification; events include `account.connected`, `post.recycled` |
|
|
91
|
+
|
|
92
|
+
The zernio-social-operator uses these endpoints only when the user explicitly asks for CRM-shaped work (contacts / broadcasts / sequences) or wants an automation wired into a campaign. Default campaign flow stays scoped to posts + queues + media + inbox + analytics.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Endpoints Used By This Kit
|
|
97
|
+
|
|
98
|
+
### Profiles
|
|
99
|
+
|
|
100
|
+
- `GET /api/v1/profiles` — list profiles on the account
|
|
101
|
+
- `GET /api/v1/profiles/<profileId>` — fetch a single profile, including the default timezone
|
|
102
|
+
|
|
103
|
+
### Accounts
|
|
104
|
+
|
|
105
|
+
- `GET /api/v1/accounts?profileId=<id>` — list connected accounts on a profile (platform + handle + accountId)
|
|
106
|
+
|
|
107
|
+
### Media upload
|
|
108
|
+
|
|
109
|
+
- `POST /api/v1/media` — multipart upload; response includes `mediaId`
|
|
110
|
+
- `GET /api/v1/media/<mediaId>` — fetch metadata of an uploaded asset
|
|
111
|
+
|
|
112
|
+
### Posts
|
|
113
|
+
|
|
114
|
+
- `POST /api/v1/posts` — schedule one post with fan-out targets
|
|
115
|
+
- `GET /api/v1/posts?profileId=<id>&status=scheduled` — list scheduled posts
|
|
116
|
+
- `GET /api/v1/posts/<postId>` — fetch a single post
|
|
117
|
+
- `DELETE /api/v1/posts/<postId>` — unschedule a post (only while `status=scheduled`)
|
|
118
|
+
|
|
119
|
+
Minimal `POST /api/v1/posts` body:
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"profileId": "prof_abc123",
|
|
124
|
+
"content": "Launch day — shipping our new kit. →",
|
|
125
|
+
"scheduledFor": "2026-05-01T09:00:00-04:00",
|
|
126
|
+
"timezone": "America/New_York",
|
|
127
|
+
"media": [{ "mediaId": "med_imgA" }],
|
|
128
|
+
"platforms": [
|
|
129
|
+
{ "platform": "twitter", "accountId": "acc_x_111" },
|
|
130
|
+
{ "platform": "linkedin", "accountId": "acc_li_222" }
|
|
131
|
+
]
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Queues (recurring schedules)
|
|
136
|
+
|
|
137
|
+
- `POST /api/v1/queues` — create a recurring queue
|
|
138
|
+
- `GET /api/v1/queues?profileId=<id>` — list queues on a profile
|
|
139
|
+
- `PUT /api/v1/queues/<queueId>` — replace queue configuration
|
|
140
|
+
- `DELETE /api/v1/queues/<queueId>` — remove queue (future slots stop; already-scheduled posts remain)
|
|
141
|
+
|
|
142
|
+
Minimal queue body:
|
|
143
|
+
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"profileId": "prof_abc123",
|
|
147
|
+
"name": "weekly-evergreen",
|
|
148
|
+
"timezone": "America/New_York",
|
|
149
|
+
"slots": [
|
|
150
|
+
{ "day": "mon", "time": "09:00", "platforms": ["twitter", "linkedin"] },
|
|
151
|
+
{ "day": "wed", "time": "12:30", "platforms": ["instagram"] },
|
|
152
|
+
{ "day": "fri", "time": "17:00", "platforms": ["bluesky", "threads"] }
|
|
153
|
+
]
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Posts attached to a queue omit `scheduledFor` and include `queueId` instead:
|
|
158
|
+
|
|
159
|
+
```json
|
|
160
|
+
{
|
|
161
|
+
"profileId": "prof_abc123",
|
|
162
|
+
"queueId": "que_xyz789",
|
|
163
|
+
"content": "Weekend builder log: three wins, one lesson.",
|
|
164
|
+
"platforms": [{ "platform": "twitter", "accountId": "acc_x_111" }]
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Inbox (DMs, comments, reviews)
|
|
169
|
+
|
|
170
|
+
- `GET /api/v1/inbox?profileId=<id>` — unified conversation list
|
|
171
|
+
- `GET /api/v1/inbox/<conversationId>` — conversation thread
|
|
172
|
+
- `POST /api/v1/inbox/<conversationId>/reply` — reply to a conversation
|
|
173
|
+
|
|
174
|
+
### Analytics
|
|
175
|
+
|
|
176
|
+
- `GET /api/v1/analytics/posts?profileId=<id>&from=<date>&to=<date>` — per-post metrics
|
|
177
|
+
- `GET /api/v1/analytics/accounts?profileId=<id>&from=<date>&to=<date>` — per-account summary
|
|
178
|
+
|
|
179
|
+
### API keys
|
|
180
|
+
|
|
181
|
+
- `POST /api/v1/api-keys` — create a new key with `scope` and `permission`
|
|
182
|
+
- `GET /api/v1/api-keys` — list existing keys
|
|
183
|
+
- `DELETE /api/v1/api-keys/<keyId>` — revoke a key
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Error Model
|
|
188
|
+
|
|
189
|
+
All non-2xx responses return:
|
|
190
|
+
|
|
191
|
+
```json
|
|
192
|
+
{
|
|
193
|
+
"error": {
|
|
194
|
+
"code": "<machine_readable_code>",
|
|
195
|
+
"message": "<human readable>",
|
|
196
|
+
"requestId": "<uuid>"
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Well-known codes the operator handles:
|
|
202
|
+
|
|
203
|
+
| HTTP | Zernio code | Behavior |
|
|
204
|
+
|---|---|---|
|
|
205
|
+
| 401 | `auth_invalid` | Key missing / malformed / revoked — surface to user, fall back to agent-only |
|
|
206
|
+
| 403 | `permission_denied` | Key lacks `read-write` scope — surface with rotate-instructions |
|
|
207
|
+
| 404 | `profile_not_found` / `account_not_found` | Correct the id or fall back to dry-run |
|
|
208
|
+
| 409 | `conflict` | Typically an idempotency collision; safe to treat as success |
|
|
209
|
+
| 422 | `validation_failed` | Manifest shape bug — fix and retry |
|
|
210
|
+
| 429 | `rate_limited` | Back off using `Retry-After` header |
|
|
211
|
+
| 5xx | `internal_error` | Retry with exponential backoff up to 3 attempts |
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## Plans and Quotas (as-of kit freeze)
|
|
216
|
+
|
|
217
|
+
| Plan | Monthly | Annual (per mo) | Profiles | Posts / month | Notes |
|
|
218
|
+
|---|---|---|---|---|---|
|
|
219
|
+
| Free | $0 | $0 | 2 | 20 | Full REST API access; useful for prototypes |
|
|
220
|
+
| Build | $19 | $16 | 10 | 120 | First paid tier |
|
|
221
|
+
| Accelerate | $49 | $41 | 50 | unlimited | Recommended for agencies + multi-client operators |
|
|
222
|
+
| Unlimited | $999 | $833 | unlimited | unlimited | Enterprise; includes higher support SLA |
|
|
223
|
+
|
|
224
|
+
All plans ship the same REST contract (posts, queues, accounts, profiles, media, inbox, analytics, contacts, broadcasts, sequences, automations, webhooks, api-keys, connect, platforms). The post-count gate is the main throttle across tiers. Rate limit is 60 requests/minute per API key at every tier.
|
|
225
|
+
|
|
226
|
+
The operator must degrade gracefully when a quota is hit: surface the Zernio error code (`rate_limited`, `quota_exhausted`) to the user, offer to switch the session into `agent-only` mode, and never silently drop scheduled posts.
|
|
227
|
+
|
|
228
|
+
## Rate Limit Handling
|
|
229
|
+
|
|
230
|
+
Default plan: 60 requests/minute per API key. The operator batches reads during account inspection and never issues more than one write per post per second.
|
|
231
|
+
|
|
232
|
+
When a 429 is returned:
|
|
233
|
+
|
|
234
|
+
1. Read `Retry-After` header (seconds)
|
|
235
|
+
2. Sleep for the returned value plus 500ms jitter
|
|
236
|
+
3. Retry the same request with the same `Idempotency-Key`
|
|
237
|
+
4. On third failure, stop and report to the user
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## SDK + Harness Options (informational)
|
|
242
|
+
|
|
243
|
+
Zernio ships official SDKs for Node.js, Python, Go, Ruby, Java, PHP, .NET, and Rust. Source repos live under [github.com/zernio-dev](https://github.com/zernio-dev).
|
|
244
|
+
|
|
245
|
+
Two primitives are directly relevant to local AI coding environments:
|
|
246
|
+
|
|
247
|
+
| Primitive | Distribution | Use from | Install |
|
|
248
|
+
|---|---|---|---|
|
|
249
|
+
| Official MCP server | bundled inside `zernio-python` | Claude Desktop, Claude Code, Cursor, any MCP-compatible IDE | `pip install zernio-sdk[mcp]` |
|
|
250
|
+
| Zernio API Claude Code skill | `zernio-api` repo | Claude Code only | `npx clawhub@latest install zernio-api` |
|
|
251
|
+
|
|
252
|
+
This kit intentionally uses the **raw REST contract** via Node's built-in `fetch()` so the operator behaves identically regardless of which local IDE the user has installed. If the user additionally plugs in Zernio's MCP server or the Claude Code skill, that is strictly complementary — the kit does not depend on either.
|
|
253
|
+
|
|
254
|
+
See `docs/local-adapters.md` for the per-IDE setup matrix and `setup/install-mcp.mjs` for the copy-paste MCP config JSON blocks.
|
|
255
|
+
|
|
256
|
+
Kit files never install or require any Zernio SDK. If the user wants to install one locally for their own tooling, that is their choice and does not affect kit behavior.
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## Security
|
|
261
|
+
|
|
262
|
+
- `ZERNIO_API_KEY` lives only in `.env` (ignored by git) and the runtime environment
|
|
263
|
+
- Outputs never include the raw key, request headers, or response payloads that contain keys
|
|
264
|
+
- `scheduling-manifest.json` contains only `clientPostId`, content, timestamps, and Zernio resource IDs — no secrets
|
|
265
|
+
- Any snippet of curl help in documentation uses `${ZERNIO_API_KEY}` as an expanded env var reference, never a literal
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Analytics Brief — Growthub · Q2 2026 Agent-Native CLI Launch
|
|
2
|
+
|
|
3
|
+
**Kit:** `growthub-zernio-social-v1`
|
|
4
|
+
**Generated:** 2026-06-02
|
|
5
|
+
**Mode:** api-live
|
|
6
|
+
**Version:** `v1`
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Period Summary
|
|
11
|
+
|
|
12
|
+
| Field | Value |
|
|
13
|
+
|---|---|
|
|
14
|
+
| Period | 2026-05-01 → 2026-05-30 |
|
|
15
|
+
| Total posts published | 82 |
|
|
16
|
+
| Platforms in scope | `twitter`, `linkedin`, `bluesky`, `youtube` |
|
|
17
|
+
| Data source | Zernio `GET /api/v1/analytics/posts` + `GET /api/v1/analytics/accounts` |
|
|
18
|
+
| Zernio profile id | prof_GRO_primary |
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Per-Platform Performance
|
|
23
|
+
|
|
24
|
+
| Platform | Posts | Impressions | Reach | Engagement rate | Follower growth | Link clicks |
|
|
25
|
+
|---|---|---|---|---|---|---|
|
|
26
|
+
| `twitter` | 30 | 184,000 | 92,300 | 4.1% | +438 | 1,240 |
|
|
27
|
+
| `linkedin` | 12 | 31,200 | 18,400 | 5.6% | +126 | 614 |
|
|
28
|
+
| `bluesky` | 13 | 22,800 | 14,100 | 6.9% | +215 | 310 |
|
|
29
|
+
| `youtube` | 9 videos (6 shorts, 3 long) | 64,500 | — | 7.2% (likes+comments / views) | +71 | — |
|
|
30
|
+
|
|
31
|
+
Engagement rate = (likes + comments + shares) / impressions × 100, normalized per platform.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Top 3 Posts
|
|
36
|
+
|
|
37
|
+
| clientPostId | Platform | Date | Engagement rate | Why it worked |
|
|
38
|
+
|---|---|---|---|---|
|
|
39
|
+
| `growthub-20260514-022` | `twitter` | 2026-05-14 | 9.4% | Step-by-step thread on shipping a full campaign end-to-end landed on Hacker News; reply chain drove 60% of the engagement |
|
|
40
|
+
| `growthub-20260501-001` | `twitter` | 2026-05-01 | 8.2% | Launch-day thread — `Agent Harness production-ready` framing matched developer Twitter's appetite for concrete builds |
|
|
41
|
+
| `growthub-20260512-019` | `linkedin` | 2026-05-12 | 7.8% | Open-source maturity ladder carousel; carousel format on LinkedIn consistently beats plain text for diagram-driven content |
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Bottom 3 Posts
|
|
46
|
+
|
|
47
|
+
| clientPostId | Platform | Date | Engagement rate | Hypothesis |
|
|
48
|
+
|---|---|---|---|---|
|
|
49
|
+
| `growthub-20260509-018` | `twitter` | 2026-05-09 | 0.9% | Weekend "what are you building" prompt — low re-share fuel, generic CTA. Replace with a pinned answer-question format next cycle. |
|
|
50
|
+
| `growthub-20260517-026` | `bluesky` | 2026-05-17 | 1.6% | Sunday OSS spotlight posted after 20:00 local — Bluesky's text feed benefits from morning placement; re-slot to 10:00. |
|
|
51
|
+
| `growthub-20260523-032` | `linkedin` | 2026-05-23 | 1.8% | Long-form text without visual on Saturday; LinkedIn engagement dips on weekends. Move weekend posts to X only. |
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Inbox Activity
|
|
56
|
+
|
|
57
|
+
| Metric | Value |
|
|
58
|
+
|---|---|
|
|
59
|
+
| Open conversations (period start) | 6 |
|
|
60
|
+
| Open conversations (period end) | 9 |
|
|
61
|
+
| Avg first-response time | 38 minutes |
|
|
62
|
+
| Replies sent | 64 |
|
|
63
|
+
| Unresolved threads > 48h | 2 |
|
|
64
|
+
|
|
65
|
+
Pulled via `GET /api/v1/inbox?profileId=prof_GRO_primary`.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Recommendations
|
|
70
|
+
|
|
71
|
+
1. **X/Twitter — double down on step-by-step threads.** Posts 22 and 01 each cleared 8% engagement. Schedule one full walkthrough thread per week anchored to a CLI command; target Thursday 12:00 local.
|
|
72
|
+
2. **LinkedIn — move to carousel-first.** Carousel posts outperformed plain text by ~2.4× in this period. Convert the next three planned LinkedIn text posts into 5-slide carousels sized 1080×1080.
|
|
73
|
+
3. **Bluesky — shift OSS spotlight to Sunday 10:00.** Data shows ≥2× engagement lift for morning placement versus evening on this audience.
|
|
74
|
+
4. **Weekend cadence — concentrate on X only.** LinkedIn and Bluesky weekend posts underperform. Free that capacity for 1 extra X post per weekend instead.
|
|
75
|
+
5. **YouTube Shorts — add captions-on by default.** Shorts with burned-in captions hit 7.9% engagement; shorts without hit 4.3%. Standardize captions-on in the platform publishing plan.
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Benchmark Comparison
|
|
80
|
+
|
|
81
|
+
| Platform | Our engagement rate | Benchmark (developer-tool peers) | Delta |
|
|
82
|
+
|---|---|---|---|
|
|
83
|
+
| `twitter` | 4.1% | 3.2% | +0.9 pts |
|
|
84
|
+
| `linkedin` | 5.6% | 4.0% | +1.6 pts |
|
|
85
|
+
| `bluesky` | 6.9% | 5.5% | +1.4 pts |
|
|
86
|
+
|
|
87
|
+
Benchmarks sourced from the brand kit's benchmark table.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Source Queries
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
GET /api/v1/analytics/posts?profileId=prof_GRO_primary&from=2026-05-01&to=2026-05-30
|
|
95
|
+
GET /api/v1/analytics/accounts?profileId=prof_GRO_primary&from=2026-05-01&to=2026-05-30
|
|
96
|
+
GET /api/v1/inbox?profileId=prof_GRO_primary
|
|
97
|
+
```
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Client Proposal — Growthub · Q2 2026 Agent-Native CLI Launch
|
|
2
|
+
|
|
3
|
+
**Kit:** `growthub-zernio-social-v1`
|
|
4
|
+
**Generated:** 2026-04-15
|
|
5
|
+
**Mode:** api-live
|
|
6
|
+
**Version:** `v1`
|
|
7
|
+
|
|
8
|
+
> Internal reference proposal for the Growthub flagship campaign. Demonstrates the expected format and grounding depth for a real client proposal.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Campaign Overview
|
|
13
|
+
|
|
14
|
+
| Field | Value |
|
|
15
|
+
|---|---|
|
|
16
|
+
| Client | Growthub |
|
|
17
|
+
| Campaign | Q2 2026 Agent-Native CLI Launch |
|
|
18
|
+
| Window | 2026-05-01 → 2026-05-30 |
|
|
19
|
+
| Primary objective | Community growth (secondary: lead generation via CLI downloads) |
|
|
20
|
+
| Platforms in scope | `twitter`, `linkedin`, `bluesky`, `youtube` |
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Platform Mix Rationale
|
|
25
|
+
|
|
26
|
+
| Platform | Role in this campaign | Why selected |
|
|
27
|
+
|---|---|---|
|
|
28
|
+
| `twitter` | Anchor — daily technical commentary | Developer community is concentrated here; 280-char format fits our voice |
|
|
29
|
+
| `linkedin` | B2B thought leadership + hiring signal | Partners and enterprise prospects live here; carousel format amplifies architectural content |
|
|
30
|
+
| `bluesky` | Early-adopter tech audience | Strong overlap with the agent-tooling audience; text-first matches Growthub's style |
|
|
31
|
+
| `youtube` | Long-form + shorts | Weekly long-form drives durable discovery; shorts feed the algorithm with CLI walkthroughs |
|
|
32
|
+
|
|
33
|
+
Instagram is deferred until team capacity supports a sustained visual pipeline.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Content Strategy
|
|
38
|
+
|
|
39
|
+
- **Theme pillars:** Product Builds (35%), Developer Tutorials (30%), Open Source (20%), Community (15%)
|
|
40
|
+
- **Format mix:** Threads on X, carousels on LinkedIn, long-form + shorts on YouTube, text on Bluesky
|
|
41
|
+
- **Cadence:** X daily, LinkedIn 3×/week, Bluesky 3×/week, YouTube 1 long + 1 short/week
|
|
42
|
+
- **Caption approach:** A/B/C variants per post — Variant A direct, B narrative, C question-hook. Selected variant is shipped; all three are logged for client review
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Deliverables Scope
|
|
47
|
+
|
|
48
|
+
| Deliverable | Included | Notes |
|
|
49
|
+
|---|---|---|
|
|
50
|
+
| Social Campaign Brief | Yes | One-time at campaign start |
|
|
51
|
+
| Content Calendar | Yes | 30-day plan, refreshed monthly |
|
|
52
|
+
| Platform Publishing Plan | Yes | Per-platform format + time window |
|
|
53
|
+
| Caption Copy Deck | Yes | A/B/C variants for every scheduled post |
|
|
54
|
+
| Scheduling Manifest | Yes | Zernio-shaped JSON + submission to `POST /api/v1/posts` |
|
|
55
|
+
| Recurring Queue | Yes | `weekly-build-log` for weekend community posts |
|
|
56
|
+
| Analytics Brief | Monthly | Pulled from `GET /api/v1/analytics/*` |
|
|
57
|
+
| Inbox reply coverage | Yes | Unified DMs/comments via `GET /api/v1/inbox` |
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Pricing Tiers
|
|
62
|
+
|
|
63
|
+
| Tier | Scope | Monthly |
|
|
64
|
+
|---|---|---|
|
|
65
|
+
| Starter | 2 platforms, 3 posts/week, monthly analytics | $2,800 |
|
|
66
|
+
| Growth | 4 platforms, daily posts, biweekly analytics, inbox coverage | $5,400 |
|
|
67
|
+
| Scale | 6+ platforms, daily posts with queues, weekly analytics, priority inbox | $9,800 |
|
|
68
|
+
|
|
69
|
+
Growthub's Q2 campaign fits **Growth** (4 platforms, daily posts, biweekly analytics, inbox coverage). Tier may move to Scale in Q3 if Instagram and Threads are added.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## ROI Projection
|
|
74
|
+
|
|
75
|
+
Based on the brand-kit benchmarks and May 2026 forecast (extrapolated from April 2026 baseline):
|
|
76
|
+
|
|
77
|
+
| KPI | Growth-tier target | Scale-tier upside |
|
|
78
|
+
|---|---|---|
|
|
79
|
+
| Impressions / month | 300,000 | 520,000 |
|
|
80
|
+
| Engagement rate | 4.5% | 5.2% |
|
|
81
|
+
| Follower growth | +750 | +1,200 |
|
|
82
|
+
| Link clicks | 1,800 | 3,100 |
|
|
83
|
+
| CLI downloads attributable to social | +1,000 | +1,800 |
|
|
84
|
+
|
|
85
|
+
Assumptions: median developer-tool engagement rate ~3.2%; Growthub's recent baseline on X is 3.8%; incremental lift comes from disciplined A/B/C variant shipping and carousel-first on LinkedIn.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Onboarding Plan
|
|
90
|
+
|
|
91
|
+
1. Connect X, LinkedIn, Bluesky, YouTube inside Zernio (`/api/v1/connect/<platform>`)
|
|
92
|
+
2. Confirm `ZERNIO_PROFILE_ID=prof_GRO_primary` and create a read-write API key scoped to it
|
|
93
|
+
3. Review and approve Content Theme Pillars in the Social Campaign Brief
|
|
94
|
+
4. Approve the Platform Publishing Plan and posting cadence
|
|
95
|
+
5. Approve the Caption Copy Deck A/B/C variants (1–2 revision cycles expected)
|
|
96
|
+
6. Submit the Scheduling Manifest with `Idempotency-Key = clientPostId`
|
|
97
|
+
7. Cadence review at week 4 alongside the first Analytics Brief
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Terms
|
|
102
|
+
|
|
103
|
+
- Content ownership stays with Growthub
|
|
104
|
+
- `ZERNIO_API_KEY`, `ANTHROPIC_API_KEY`, and any per-platform OAuth tokens stay inside Growthub's Zernio account and local `.env` — never included in deliverables
|
|
105
|
+
- Cancellation: 30-day written notice
|
|
106
|
+
- Revisions: two full revision cycles per deliverable included in each tier
|