Skip to content

Commit d76b4f2

Browse files
authored
feat: v0.5.0, API changes (#15)
Co-authored-by: chrisdengso <8185683+chrisdengso@users.noreply.github.com>
1 parent 05f08ba commit d76b4f2

62 files changed

Lines changed: 14745 additions & 5931 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.speakeasy/gen.lock‎

Lines changed: 280 additions & 37 deletions
Large diffs are not rendered by default.

‎.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.4.0
35+
version: 0.5.0
3636
additionalDependencies: {}
3737
agentEnvironmentDetection: true
3838
arrayFlagFormat: repeatable

‎.speakeasy/openapi.json‎

Lines changed: 6646 additions & 4609 deletions
Large diffs are not rendered by default.

‎CHANGELOG.md‎

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

3+
## 0.5.0 (2026-10-26)
4+
5+
Full Changelog: [v0.4.0...v0.5.0](https://github.com/moderation-api/cli/compare/v0.4.0...v0.5.0)
6+
7+
### ⚠ Breaking changes
8+
9+
- `GET /authors`: removed the enum value `reportCount` from the `query` request parameter `sortBy`
10+
- `GET /queue/{id}`: the response property `queue/description` became nullable for the status `200`
11+
- `GET /queue/{id}`: removed the required property `queue/filter` from the response with the `200` status
12+
- `GET /queue/{id}/items`: added `subschema #1, subschema #2` to the `data/items/content` response property `anyOf` list for the response status `200`
13+
- `GET /queue/{id}/items`: the response property `data/items/authorId` became nullable for the status `200`
14+
- `GET /queue/{id}/items`: the response property `data/items/contentType` became nullable for the status `200`
15+
- `GET /queue/{id}/items`: the response property `data/items/conversationId` became nullable for the status `200`
16+
- `GET /queue/{id}/items`: the response property `data/items/language` became nullable for the status `200`
17+
- `GET /queue/{id}/items`: the response property `data/items/labels/items/flagged` became optional for the status `200`
18+
- `GET /queue/{id}/items`: the `data/items/content` response's property `type` changed from `string` to `any` for status `200`
19+
- `POST /queue/{id}/items/{itemId}/resolve`: removed the request body
20+
- `POST /queue/{id}/items/{itemId}/unresolve`: removed the request body
21+
- `GET /queue/{id}/stats`: the response property `topReviewers/items/name` became nullable for the status `200`
22+
- `GET /queue/{id}/stats`: the response property `topReviewers/items/userId` became nullable for the status `200`
23+
- `GET /queue/{id}/stats`: removed the required property `actionStats` from the response with the `200` status
24+
- `GET /queue/{id}/stats`: removed the required property `reviewStats/averageTimeToReview` from the response with the `200` status
25+
- `GET /queue/{id}/stats`: removed the required property `topReviewers/items/averageTimePerReview` from the response with the `200` status
26+
- `GET /queue/{id}/stats`: removed the required property `topReviewers/items/topActions` from the response with the `200` status
27+
- `GET /queue/{id}/stats`: removed the required property `trends/flaggedContentTrends` from the response with the `200` status
28+
29+
### API changes
30+
31+
- `GET /actions`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
32+
- `POST /actions/execute`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
33+
- `POST /actions/{actionId}/execute`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
34+
- `DELETE /actions/{id}`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
35+
- `GET /actions/{id}`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
36+
- `PUT /actions/{id}`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
37+
- `GET /auth`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
38+
- `GET /authors`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
39+
- `DELETE /authors/{id}`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
40+
- `GET /authors/{id}`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
41+
- `PUT /authors/{id}`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
42+
- `DELETE /channels/{id}`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
43+
- `GET /channels/{id}`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
44+
- `PUT /channels/{id}`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
45+
- `POST /channels/{id}/duplicate`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
46+
- `DELETE /projects/{id}`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
47+
- `GET /projects/{id}`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
48+
- `PUT /projects/{id}`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
49+
- `POST /projects/{id}/api-keys`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
50+
- `POST /projects/{id}/duplicate`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
51+
- `GET /projects/{projectId}/channels`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
52+
- `POST /projects/{projectId}/channels`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
53+
- `GET /queue/{id}`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
54+
- `GET /queue/{id}/items`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
55+
- `GET /queue/{id}/stats`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
56+
- `DELETE /webhooks/{id}`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
57+
- `GET /webhooks/{id}`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
58+
- `PUT /webhooks/{id}`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
59+
- `GET /wordlist`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
60+
- `GET /wordlist/{id}`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
61+
- `PUT /wordlist/{id}`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
62+
- `GET /wordlist/{id}/embedding-status`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
63+
- `DELETE /wordlist/{id}/words`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
64+
- `POST /wordlist/{id}/words`: added the new `queue_item_not_found` enum value to the `code` response property for the response status `404`
65+
- `GET /authors`: deleted the `query` request parameter `contentTypes`
66+
- `GET /queue/{id}/items`: deleted the `query` request parameter `sortDirection`
67+
- `GET /queue/{id}/items`: deleted the `query` request parameter `sortField`
68+
- a breaking change was detected but the version is still `1.1.0`
69+
- `GET /analytics/authors`: endpoint added
70+
- `GET /analytics/automation`: endpoint added
71+
- `GET /analytics/channels`: endpoint added
72+
- `GET /analytics/policies`: endpoint added
73+
- `GET /analytics/summary`: endpoint added
74+
- `GET /analytics/volumes`: endpoint added
75+
- `POST /feedback`: endpoint added
76+
- `GET /queue`: endpoint added
77+
- `GET /queue/{id}`: the `queue/resolvedItemsCount` response's property `type` was narrowed from `number` to `integer` for status `200`
78+
- `GET /queue/{id}`: the `queue/totalItemsCount` response's property `type` was narrowed from `number` to `integer` for status `200`
79+
- `GET /queue/{id}`: the `queue/unresolvedItemsCount` response's property `type` was narrowed from `number` to `integer` for status `200`
80+
- `GET /queue/{id}`: added the required property `queue/isDefault` to the response with the `200` status
81+
- `GET /queue/{id}/items`: added the new optional `query` request parameter `sort`
82+
- `GET /queue/{id}/items`: added the optional property `data/items/labels/items/manual` to the response with the `200` status
83+
- `GET /queue/{id}/items`: added the optional property `data/items/labels/items/matches` to the response with the `200` status
84+
- `GET /queue/{id}/items`: added the optional property `data/items/labels/items/shadow_flagged` to the response with the `200` status
85+
- `GET /queue/{id}/items`: removed the optional property `data/items/actions` from the response with the `200` status
86+
- `GET /queue/{id}/items`: the response property `data/items/authorId` became required for the status `200`
87+
- `GET /queue/{id}/items`: the response property `data/items/contentType` became required for the status `200`
88+
- `GET /queue/{id}/items`: the response property `data/items/conversationId` became required for the status `200`
89+
- `GET /queue/{id}/items`: the response property `data/items/language` became required for the status `200`
90+
- `GET /queue/{id}/items`: added the required property `data/items/contentId` to the response with the `200` status
91+
- `GET /queue/{id}/items`: added the required property `data/items/severity` to the response with the `200` status
92+
- `POST /queue/{id}/items/resolve`: endpoint added
93+
- `POST /queue/{id}/items/{itemId}/resolve`: removed the optional property `comment` from the response with the `200` status
94+
- `POST /queue/{id}/items/{itemId}/unresolve`: the `status` response property for the response status `200` was restricted to a list of enum values
95+
- `GET /queue/{id}/stats`: removed the optional property `topReviewers/items/accuracyScore` from the response with the `200` status
96+
- `GET /queue/{id}/stats`: the `reviewStats/totalPending` response's property `type` was narrowed from `number` to `integer` for status `200`
97+
- `GET /queue/{id}/stats`: the `reviewStats/totalReviewed` response's property `type` was narrowed from `number` to `integer` for status `200`
98+
- `GET /queue/{id}/stats`: the `topReviewers/items/reviewCount` response's property `type` was narrowed from `number` to `integer` for status `200`
99+
- `GET /queue/{id}/stats`: the `trends/dailyReviewCounts/items/count` response's property `type` was narrowed from `number` to `integer` for status `200`
100+
- `POST /wordlist`: endpoint added
101+
3102
## 0.4.0 (2026-10-23)
4103

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

‎README.md‎

Lines changed: 16 additions & 2 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,6 +144,8 @@ modapi init --domain acme.com \
144144
--brief "Stop contact details shared outside the platform, scams and harassment"
145145
```
146146

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+
147149
`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):
148150

149151
```bash
@@ -362,18 +364,29 @@ modapi projects list --secret-key "$MODAPI_ORGANIZATION_KEY"
362364
<details open>
363365
<summary>Available commands</summary>
364366

367+
* [`analytics`](docs/modapi_analytics.md) - Operations for analytics
368+
* [`summary`](docs/modapi_analytics_summary.md) - Get the analytics summary
369+
* [`policies`](docs/modapi_analytics_policies.md) - Get the most flagged policies
370+
* [`authors`](docs/modapi_analytics_authors.md) - Get the most flagged authors
371+
* [`channels`](docs/modapi_analytics_channels.md) - Get analytics per channel
372+
* [`volumes`](docs/modapi_analytics_volumes.md) - Get volumes over time
373+
* [`automation`](docs/modapi_analytics_automation.md) - Get the automation breakdown
365374
* [`authors`](docs/modapi_authors.md) - Operations for authors
366375
* [`list`](docs/modapi_authors_list.md) - List authors
367376
* [`create`](docs/modapi_authors_create.md) - Create a new author
368377
* [`retrieve`](docs/modapi_authors_retrieve.md) - Get author details
369378
* [`update`](docs/modapi_authors_update.md) - Update author details
370379
* [`delete`](docs/modapi_authors_delete.md) - Delete an author
380+
* [`feedback`](docs/modapi_feedback.md) - Operations for feedback
381+
* [`create`](docs/modapi_feedback_create.md) - Send feedback
371382
* [`queue`](docs/modapi_queue.md) - Operations for queue
383+
* [`list`](docs/modapi_queue_list.md) - List queues
372384
* [`retrieve`](docs/modapi_queue_retrieve.md) - Get a queue
373385
* [`get-stats`](docs/modapi_queue_get-stats.md) - Get queue statistics
374386
* [`items`](docs/modapi_queue_items.md) - Operations for items
375-
* [`list`](docs/modapi_queue_items_list.md) - Get queue items
387+
* [`list`](docs/modapi_queue_items_list.md) - List queue items
376388
* [`resolve`](docs/modapi_queue_items_resolve.md) - Resolve a queue item
389+
* [`resolve-many`](docs/modapi_queue_items_resolve-many.md) - Resolve queue items
377390
* [`unresolve`](docs/modapi_queue_items_unresolve.md) - Unresolve a queue item
378391
* [`actions`](docs/modapi_actions.md) - Operations for actions
379392
* [`list`](docs/modapi_actions_list.md) - List moderation actions
@@ -394,6 +407,7 @@ modapi projects list --secret-key "$MODAPI_ORGANIZATION_KEY"
394407
* [`retrieve`](docs/modapi_account_retrieve.md) - Get account details
395408
* [`wordlist`](docs/modapi_wordlist.md) - Operations for wordlist
396409
* [`list`](docs/modapi_wordlist_list.md) - List wordlists
410+
* [`create`](docs/modapi_wordlist_create.md) - Create wordlist
397411
* [`retrieve`](docs/modapi_wordlist_retrieve.md) - Get wordlist
398412
* [`update`](docs/modapi_wordlist_update.md) - Update wordlist
399413
* [`get-embedding-status`](docs/modapi_wordlist_get-embedding-status.md) - Get embedding status

‎internal/cli/analytics/authors.go‎

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.
2+
3+
package analytics
4+
5+
import (
6+
"fmt"
7+
"github.com/moderation-api/cli/internal/client"
8+
"github.com/moderation-api/cli/internal/flagutil"
9+
"github.com/moderation-api/cli/internal/output"
10+
"github.com/moderation-api/cli/internal/sdk"
11+
"github.com/moderation-api/cli/internal/sdk/models/operations"
12+
"github.com/moderation-api/cli/internal/usage"
13+
"github.com/spf13/cobra"
14+
)
15+
16+
var authorsCmdMeta = []flagutil.FlagMeta{
17+
{FlagName: "range", Shorthand: "r", FieldPath: "Range", Kind: flagutil.FlagKindEnum, Optional: true, HasDefault: true, DefaultStr: "30d", EnumValues: []string{"24h", "7d", "30d", "90d"}, Description: "The time window. '24h' is the last 24 hours, in hourly buckets. '7d', '30d' and '90d' are whole UTC days that end with today, in daily buckets. (options: 24h, 7d, 30d, 90d)"},
18+
{FlagName: "channel", Shorthand: "c", FieldPath: "Channel", Kind: flagutil.FlagKindString, Optional: true, Description: "string value"},
19+
{FlagName: "limit", Shorthand: "l", FieldPath: "Limit", Kind: flagutil.FlagKindInt64, Optional: true, HasDefault: true, DefaultInt: 6, HasMinimum: true, Minimum: 1, HasMaximum: true, Maximum: 50, Description: "integer value"},
20+
{FlagName: "project-id", Shorthand: "p", FieldPath: "ProjectID", Kind: flagutil.FlagKindString, Optional: true, Description: "The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error."},
21+
}
22+
23+
// initAuthorsCmd initializes the authors command.
24+
func initAuthorsCmd(parent *cobra.Command) error {
25+
var cmd = &cobra.Command{
26+
Use: "authors",
27+
Short: "Get the most flagged authors",
28+
Long: "Get the authors with the most flagged content in a time window, largest first.",
29+
Example: " modapi analytics authors",
30+
Args: cobra.NoArgs,
31+
RunE: runAuthorsCmd,
32+
Annotations: map[string]string{
33+
"speakeasy_operation": "getAnalyticsAuthors",
34+
},
35+
}
36+
flagutil.RegisterFlags(cmd, authorsCmdMeta)
37+
if err := flagutil.ValidateMeta[operations.GetAnalyticsAuthorsRequest](authorsCmdMeta); err != nil {
38+
return fmt.Errorf("invalid metadata for authors: %w", err)
39+
}
40+
parent.AddCommand(cmd)
41+
return nil
42+
}
43+
44+
// runAuthorsCmd executes the authors command.
45+
func runAuthorsCmd(cmd *cobra.Command, args []string) error {
46+
if usage.UsageRequested(cmd) {
47+
return usage.EmitSchema(cmd, cmd.OutOrStdout())
48+
}
49+
req, err := flagutil.BuildRequest[operations.GetAnalyticsAuthorsRequest](cmd, authorsCmdMeta, "", "")
50+
if err != nil {
51+
return flagutil.WithCLIValidation(err)
52+
}
53+
s, err := client.NewClient(cmd)
54+
if err != nil {
55+
return err
56+
}
57+
sdkOpts, err := output.PrepareCallOpts(cmd)
58+
if err != nil {
59+
return err
60+
}
61+
// Dry-run: force skip deserialization so the synthetic empty response
62+
// does not cause parse failures in typed response handling.
63+
if client.IsDryRun(cmd) {
64+
sdkOpts = append(sdkOpts, operations.WithSkipDeserialization())
65+
}
66+
if err := output.ValidateGlobalServerIndex(cmd, len(sdk.ServerList)); err != nil {
67+
return err
68+
}
69+
if output.WantsRawJSON(cmd) {
70+
sdkOpts = append(sdkOpts, operations.WithSkipDeserialization())
71+
}
72+
stopProgress := output.StartRequestProgress(cmd)
73+
defer stopProgress()
74+
res, err := s.Analytics.Authors(cmd.Context(), req, sdkOpts...)
75+
stopProgress()
76+
if err != nil {
77+
return output.Error(cmd, err)
78+
}
79+
80+
if err := output.Result(cmd, res); err != nil {
81+
return err
82+
}
83+
return nil
84+
}

0 commit comments

Comments
 (0)