Skip to content

Commit 1ebadcd

Browse files
chrisdengsogithub-actions[bot]
authored andcommitted
feat: v0.4.0, API changes
1 parent 3810e58 commit 1ebadcd

16 files changed

Lines changed: 828 additions & 37 deletions

File tree

‎.speakeasy/gen.lock‎

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
lockVersion: 2.0.0
22
id: f6fec850-ef66-45dd-9a18-cec7cc0801ce
33
management:
4-
docChecksum: a23b8f20e57fbf8dec16be6319a7398f
4+
docChecksum: 1f41f7f3f1f9652138167d27f8b4518c
55
docVersion: 1.1.0
66
speakeasyVersion: internal
77
generationVersion: internal
8-
releaseVersion: 0.3.3
9-
configChecksum: a95df217f2ce238441199a6ea3f715fe
8+
releaseVersion: 0.4.0
9+
configChecksum: 4273d5885cbbeaedeb3ad7cdeb96d994
1010
repoURL: https://github.com/moderation-api/cli
1111
installationURL: https://github.com/moderation-api/cli
1212
published: true
@@ -96,6 +96,10 @@ trackedFiles:
9696
last_write_checksum: sha1:5db89edd5a5f6b7867090c973744f629e4498422
9797
internal/cli/masking.go:
9898
last_write_checksum: sha1:5a69fa055d628c1b8507cd123f3cd18309aa9a53
99+
internal/cli/projects/apikeys/create.go:
100+
last_write_checksum: sha1:535e92c12f0efd0833064bfb4ffb4600b0757c1b
101+
internal/cli/projects/apikeys/root.go:
102+
last_write_checksum: sha1:33a648830982cc6f4cfcc3a561c2848af3e336ff
99103
internal/cli/projects/create.go:
100104
last_write_checksum: sha1:2838c87019ac2cc223f135e088213eff20d185c9
101105
internal/cli/projects/delete.go:
@@ -107,7 +111,7 @@ trackedFiles:
107111
internal/cli/projects/retrieve.go:
108112
last_write_checksum: sha1:dc13d97de4946558f0675a5044cb0e243f22a4a5
109113
internal/cli/projects/root.go:
110-
last_write_checksum: sha1:643c0a49b24d09ea96931240c34e98daaa1b390d
114+
last_write_checksum: sha1:4145379bf6cfa4963ef6b41beaf5c568333ce73f
111115
internal/cli/projects/update.go:
112116
last_write_checksum: sha1:86360b44e47dfff918db06784b723a60a2892fe7
113117
internal/cli/queue/getstats.go:
@@ -127,7 +131,7 @@ trackedFiles:
127131
internal/cli/root.go:
128132
last_write_checksum: sha1:d00799a3804f87479242f16bf520cb593f79ba8e
129133
internal/cli/version.go:
130-
last_write_checksum: sha1:a77aa9a27f89f066ed45081e1f453d5f8780ac78
134+
last_write_checksum: sha1:a8ab87a20abe46d2c0f4928cafee3c713021c841
131135
internal/cli/webhooks/create.go:
132136
last_write_checksum: sha1:98c73266c8954efcf0da2493ae41909df45a38f0
133137
internal/cli/webhooks/delete.go:
@@ -224,6 +228,8 @@ trackedFiles:
224228
last_write_checksum: sha1:c73d83f641b59a97479506597334a95539d34e16
225229
internal/sdk/actions.go:
226230
last_write_checksum: sha1:d6f0d54d24673ae13bd908680018b71e7d520820
231+
internal/sdk/apikeys.go:
232+
last_write_checksum: sha1:eb2143b8ecfa3044b599462841bd90d70671bf3b
227233
internal/sdk/authors.go:
228234
last_write_checksum: sha1:01eb0e9f6fa3fd9987edb54429293271203c7ec6
229235
internal/sdk/channels.go:
@@ -254,6 +260,8 @@ trackedFiles:
254260
last_write_checksum: sha1:99268e4c4433540e746d421b6a16be06e2458770
255261
internal/sdk/models/components/project.go:
256262
last_write_checksum: sha1:be428edb928147e28c4c15c0ebdef472b6c25461
263+
internal/sdk/models/components/projectapikey.go:
264+
last_write_checksum: sha1:4c561bd766b8db2042e9e6da609e3dccbfa75685
257265
internal/sdk/models/components/projectwithkey.go:
258266
last_write_checksum: sha1:a8186b049b303d92ef01688eca3e05ea9dabef2b
259267
internal/sdk/models/components/publicauthor.go:
@@ -272,6 +280,8 @@ trackedFiles:
272280
last_write_checksum: sha1:7418ba8327dcfd0855b6e1eb972bd8581a468635
273281
internal/sdk/models/operations/createproject.go:
274282
last_write_checksum: sha1:1387c903814ffe16e3683916acff2216f912fa6a
283+
internal/sdk/models/operations/createprojectapikey.go:
284+
last_write_checksum: sha1:5a1c5f987689e312de108a7888b86c7353b0eec6
275285
internal/sdk/models/operations/createwebhook.go:
276286
last_write_checksum: sha1:93c0a33438a7034b3a8f2d689b168ee254c42e79
277287
internal/sdk/models/operations/deleteaction.go:
@@ -367,13 +377,13 @@ trackedFiles:
367377
internal/sdk/models/sdkerrors/sdkdefaulterror.go:
368378
last_write_checksum: sha1:437b3a3eacb54d8648a68f80b3cd38fa5019f006
369379
internal/sdk/moderationapi.go:
370-
last_write_checksum: sha1:f1f147d2cf835423ff61ed5b03e4a8b2cd08a56c
380+
last_write_checksum: sha1:dddc315a89c2907ff24d91c28784ed97fe738c5f
371381
internal/sdk/optionalnullable/optionalnullable.go:
372382
last_write_checksum: sha1:b828c94c45116e632925027e4e2c211e971e04e2
373383
internal/sdk/optionalnullable/optionalnullable_test.go:
374384
last_write_checksum: sha1:d3991667754ed67db803aeab4a6239f6f9a1be37
375385
internal/sdk/projects.go:
376-
last_write_checksum: sha1:6c561630b561c50f8d0758c744f9006180e2e77b
386+
last_write_checksum: sha1:77b021be8e1ea6b2d2aef13a536a922d0b614bb9
377387
internal/sdk/queue.go:
378388
last_write_checksum: sha1:e7ad9e07ed4c6f302ac8b7123a7c4e8d9b4e034e
379389
internal/sdk/retry/config.go:
@@ -427,9 +437,9 @@ trackedFiles:
427437
internal/testclient/testclient.go:
428438
last_write_checksum: sha1:7107e59d336235c44af152c5a61ee3896a7841fa
429439
internal/usage/bodyschemas.go:
430-
last_write_checksum: sha1:06404c8b3b7c87ea76f8722c2aeaa1d17baac650
440+
last_write_checksum: sha1:f766420e385b255888deecba3146cc31d22dc3d3
431441
internal/usage/schema.go:
432-
last_write_checksum: sha1:7d18cd61a609d94a72ef1c29a10141425c2d2620
442+
last_write_checksum: sha1:04bfae1bd9a42fc9ffc14b31e09bff0d4c326b65
433443
scripts/install.ps1:
434444
last_write_checksum: sha1:bd3a52c28f647ed881c6e8d72abf2d84216976c9
435445
scripts/install.sh:
@@ -1184,4 +1194,24 @@ examples:
11841194
application/json: {"type": "not_found_error", "code": "resource_not_found", "message": "Not found", "request_id": "h8fkz6kkzoa446ffve37atys", "doc_url": "https://insecure-premium.com/"}
11851195
"429":
11861196
application/json: {"type": "rate_limit_error", "code": "rate_limit_exceeded", "message": "Rate limit exceeded", "request_id": "h8fkz6kkzoa446ffve37atys", "doc_url": "https://upset-hydrant.info/"}
1197+
createProjectApiKey:
1198+
speakeasy-default-create-project-api-key:
1199+
parameters:
1200+
path:
1201+
id: "<id>"
1202+
requestBody:
1203+
application/json: {"name": "API key"}
1204+
responses:
1205+
"200":
1206+
application/json: {"id": "<id>", "name": "<value>", "projectId": "<id>", "createdAt": "1711588645112", "secretKey": "<value>"}
1207+
"400":
1208+
application/json: {"type": "invalid_request_error", "code": "invalid_request", "message": "Invalid input data", "request_id": "h8fkz6kkzoa446ffve37atys", "doc_url": "https://rusty-responsibility.com"}
1209+
"401":
1210+
application/json: {"type": "authentication_error", "code": "unauthorized", "message": "Authorization not provided", "request_id": "h8fkz6kkzoa446ffve37atys", "doc_url": "https://compassionate-chow.net"}
1211+
"403":
1212+
application/json: {"type": "permission_error", "code": "permission_denied", "message": "Insufficient access", "request_id": "h8fkz6kkzoa446ffve37atys", "doc_url": "https://buzzing-convection.com/"}
1213+
"404":
1214+
application/json: {"type": "not_found_error", "code": "resource_not_found", "message": "Not found", "request_id": "h8fkz6kkzoa446ffve37atys", "doc_url": "https://impractical-bin.info/"}
1215+
"429":
1216+
application/json: {"type": "rate_limit_error", "code": "rate_limit_exceeded", "message": "Rate limit exceeded", "request_id": "h8fkz6kkzoa446ffve37atys", "doc_url": "https://damaged-bandwidth.name"}
11871217
examplesVersion: 1.0.2

‎.speakeasy/gen.yaml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ generation:
3232
generateNewTests: true
3333
skipResponseBodyAssertions: false
3434
cli:
35-
version: 0.3.3
35+
version: 0.4.0
3636
additionalDependencies: {}
3737
agentEnvironmentDetection: true
3838
arrayFlagFormat: repeatable

‎.speakeasy/openapi.json‎

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10002,6 +10002,124 @@
1000210002
}
1000310003
}
1000410004
},
10005+
"/projects/{id}/api-keys": {
10006+
"post": {
10007+
"operationId": "createProjectApiKey",
10008+
"summary": "Create a project API key",
10009+
"description": "Create a new secret API key for a project and return it. Give each app or computer its own key, so you can revoke one without breaking the others. The project's existing keys keep working. Needs the `projects:write` permission.",
10010+
"tags": [
10011+
"Projects"
10012+
],
10013+
"security": [
10014+
{
10015+
"Authorization": []
10016+
}
10017+
],
10018+
"parameters": [
10019+
{
10020+
"in": "path",
10021+
"name": "id",
10022+
"schema": {
10023+
"type": "string",
10024+
"description": "The ID of the project."
10025+
},
10026+
"required": true,
10027+
"description": "The ID of the project."
10028+
}
10029+
],
10030+
"requestBody": {
10031+
"required": true,
10032+
"content": {
10033+
"application/json": {
10034+
"schema": {
10035+
"type": "object",
10036+
"properties": {
10037+
"name": {
10038+
"default": "API key",
10039+
"description": "A name for the key, shown on the API keys page of the dashboard. Name it after where the key is used, for example the app or the computer.",
10040+
"type": "string",
10041+
"minLength": 1,
10042+
"maxLength": 50
10043+
}
10044+
}
10045+
}
10046+
}
10047+
}
10048+
},
10049+
"responses": {
10050+
"200": {
10051+
"description": "API key created successfully",
10052+
"content": {
10053+
"application/json": {
10054+
"schema": {
10055+
"$ref": "#/components/schemas/ProjectApiKey"
10056+
}
10057+
}
10058+
}
10059+
},
10060+
"400": {
10061+
"description": "Invalid input data",
10062+
"content": {
10063+
"application/json": {
10064+
"schema": {
10065+
"$ref": "#/components/schemas/BadRequestError"
10066+
}
10067+
}
10068+
}
10069+
},
10070+
"401": {
10071+
"description": "Authorization not provided",
10072+
"content": {
10073+
"application/json": {
10074+
"schema": {
10075+
"$ref": "#/components/schemas/AuthenticationError"
10076+
}
10077+
}
10078+
}
10079+
},
10080+
"403": {
10081+
"description": "Insufficient access",
10082+
"content": {
10083+
"application/json": {
10084+
"schema": {
10085+
"$ref": "#/components/schemas/PermissionDeniedError"
10086+
}
10087+
}
10088+
}
10089+
},
10090+
"404": {
10091+
"description": "Not found",
10092+
"content": {
10093+
"application/json": {
10094+
"schema": {
10095+
"$ref": "#/components/schemas/NotFoundError"
10096+
}
10097+
}
10098+
}
10099+
},
10100+
"429": {
10101+
"description": "Too many requests. Retry after the number of seconds in the `Retry-After` header.",
10102+
"content": {
10103+
"application/json": {
10104+
"schema": {
10105+
"$ref": "#/components/schemas/RateLimitError"
10106+
}
10107+
}
10108+
}
10109+
}
10110+
},
10111+
"x-speakeasy-group": "projects.apiKeys",
10112+
"x-speakeasy-name-override": "create",
10113+
"x-speakeasy-mcp": {
10114+
"title": "Create a project API key",
10115+
"scopes": [
10116+
"write"
10117+
],
10118+
"readOnlyHint": false,
10119+
"destructiveHint": false
10120+
}
10121+
}
10122+
},
1000510123
"/projects/{projectId}/channels": {
1000610124
"get": {
1000710125
"operationId": "listChannels",
@@ -11314,6 +11432,39 @@
1131411432
],
1131511433
"additionalProperties": false
1131611434
},
11435+
"ProjectApiKey": {
11436+
"type": "object",
11437+
"properties": {
11438+
"id": {
11439+
"type": "string",
11440+
"description": "The ID of the API key."
11441+
},
11442+
"name": {
11443+
"type": "string",
11444+
"description": "The key's name."
11445+
},
11446+
"projectId": {
11447+
"type": "string",
11448+
"description": "The ID of the project the key belongs to."
11449+
},
11450+
"createdAt": {
11451+
"description": "When the key was created.",
11452+
"type": "string"
11453+
},
11454+
"secretKey": {
11455+
"type": "string",
11456+
"description": "The new secret API key. Use it to moderate content in this project. It is also shown in the project's settings."
11457+
}
11458+
},
11459+
"required": [
11460+
"id",
11461+
"name",
11462+
"projectId",
11463+
"createdAt",
11464+
"secretKey"
11465+
],
11466+
"additionalProperties": false
11467+
},
1131711468
"Channel": {
1131811469
"type": "object",
1131911470
"properties": {

‎CHANGELOG.md‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Changelog
22

3+
## 0.4.0 (2026-10-23)
4+
5+
Full Changelog: [v0.3.3...v0.4.0](https://github.com/moderation-api/cli/compare/v0.3.3...v0.4.0)
6+
7+
### API changes
8+
9+
- `POST /projects/{id}/api-keys`: endpoint added
10+
311
## 0.3.3 (2026-10-23)
412

513
Full Changelog: [v0.3.2...v0.3.3](https://github.com/moderation-api/cli/compare/v0.3.2...v0.3.3)

‎README.md‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ modapi content submit --content '{"type":"text","text":"Hey, check out my profil
128128
<!-- Start Custom [guide] -->
129129
## Set up Moderation API in your project
130130

131-
Run `init` in your project's directory. It signs you in if needed, creates a Moderation API project, and writes the project's keys to your env file:
131+
Run `init` in your project's directory. It links one of your Moderation API projects or creates a new one, and writes the project's keys to your env file:
132132

133133
```bash
134134
modapi login # once per machine; opens the browser
@@ -144,10 +144,12 @@ modapi init --domain acme.com \
144144
--brief "Stop contact details shared outside the platform, scams and harassment"
145145
```
146146

147-
`init` does not change your code. To add the moderation calls, let your coding agent do it with the [setup skill](https://github.com/moderation-api/skills):
147+
To connect a directory to a project you already have, run `modapi link` (or `modapi link "<project name>"`). It makes a new key for the project, so you can revoke it on its own. Agents and scripts pass `init --project <id or name>` or `init --new` instead of answering the question.
148+
149+
`init` does not change your code. To add the moderation calls, let your coding agent do it with the setup skill:
148150

149151
```bash
150-
npx skills add moderation-api/skills
152+
npx skills add moderation-api/cli
151153
```
152154

153155
Then ask your agent to "set up Moderation API". The skill finds where users create content, adds the moderation call, handles the result and sets up webhooks, asking you before each change.
@@ -409,6 +411,8 @@ modapi projects list --secret-key "$MODAPI_ORGANIZATION_KEY"
409411
* [`update`](docs/modapi_projects_update.md) - Update a project
410412
* [`delete`](docs/modapi_projects_delete.md) - Delete a project
411413
* [`duplicate`](docs/modapi_projects_duplicate.md) - Duplicate a project
414+
* [`api-keys`](docs/modapi_projects_api-keys.md) - Operations for api-keys
415+
* [`create`](docs/modapi_projects_api-keys_create.md) - Create a project API key
412416
* [`channels`](docs/modapi_channels.md) - Operations for channels
413417
* [`list`](docs/modapi_channels_list.md) - List channels
414418
* [`create`](docs/modapi_channels_create.md) - Create a channel

0 commit comments

Comments
 (0)