Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: Antwork Analytics API
version: v1
description: 'Draft, schedule and publish social posts on the accounts connected to your Antwork workspaces. Reference: https://antwork.io/docs/api'
servers:
- url: https://antwork.io/api/v1
security:
- apiKey: []
tags:
- name: Analytics
paths:
/analytics/daily:
get:
operationId: getDailyEngagement
summary: Engagement earned per day, as a table; or one post’s per-day history
description: 'The per-day and follower tables MCP get_performance returns, from the same function. A null cell is a day not measured or a field the platform does not report; a 0 is a measured zero. `reachBasis` names what `impressions` counts, and different bases do not add, so the `all` row’s impressions is null on a mixed day. The daily rollup runs once a day.
Scope: `read`.
Docs: https://antwork.io/docs/api/daily'
x-antwork-scope: read
externalDocs:
url: https://antwork.io/docs/api/daily
parameters:
- name: workspaceId
in: query
required: false
description: Required when the account has more than one workspace and no `postId` is given.
schema:
type: string
- name: days
in: query
required: false
description: Trailing window in days, today included, 1 to 365. Default 30; with `postId`, the whole history.
schema:
type: integer
minimum: 1
maximum: 365
- name: postId
in: query
required: false
description: One post’s history instead of the workspace’s.
schema:
type: string
responses:
'200':
description: The workspace table (with `followers`), or the post’s.
content:
application/json:
schema:
$ref: '#/components/schemas/EngagementHistory'
'400':
description: 'The request was refused. Codes: `workspace_required`, `invalid_filter`.'
x-error-codes:
- workspace_required
- invalid_filter
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: 'No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.'
x-error-codes:
- api_key_missing
- api_key_malformed
- api_key_unknown
- api_key_revoked
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: 'The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.'
x-error-codes:
- insufficient_scope
- subscription_inactive
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: 'Not found on this account. Codes: `workspace_not_found`, `post_not_found`.'
x-error-codes:
- workspace_not_found
- post_not_found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: 'Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.'
x-error-codes:
- rate_limit_burst
- rate_limit_daily
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: 'Something went wrong on our end. Codes: `internal_error`.'
x-error-codes:
- internal_error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
tags:
- Analytics
/analytics/performance:
get:
operationId: getPerformance
summary: Lifetime metrics per published post, and per-platform totals, over a window
description: 'The same numbers as the analytics page and MCP get_performance. Metrics refresh every six hours. Bounded by the window and `limit`, not paged.
Scope: `read`.
Docs: https://antwork.io/docs/api/performance'
x-antwork-scope: read
externalDocs:
url: https://antwork.io/docs/api/performance
parameters:
- name: workspaceId
in: query
required: false
description: Required when the account has more than one workspace.
schema:
type: string
- name: days
in: query
required: false
description: Window ending now, 1 to 730. Default 30.
schema:
type: integer
minimum: 1
maximum: 730
default: 30
- name: from
in: query
required: false
description: YYYY-MM-DD, with `to`; wins over `days`.
schema:
type: string
format: date
- name: to
in: query
required: false
description: YYYY-MM-DD, with `from`.
schema:
type: string
format: date
- name: platform
in: query
required: false
description: Only this platform.
schema:
type: string
- name: accountId
in: query
required: false
description: Only this account; wins over `platform`.
schema:
type: string
- name: compare
in: query
required: false
description: '`true` adds `previous`: the same totals over the preceding window.'
schema:
type: boolean
- name: findings
in: query
required: false
description: '`true` adds `findings` (and `previous`): the period comparison, top and bottom posts, best windows, follower change and today''s position against the daily cap.'
schema:
type: boolean
- name: limit
in: query
required: false
description: Rows, 1 to 500. Default 200.
schema:
type: integer
minimum: 1
maximum: 500
default: 200
responses:
'200':
description: The report.
content:
application/json:
schema:
$ref: '#/components/schemas/Performance'
'400':
description: 'The request was refused. Codes: `workspace_required`, `invalid_filter`, `invalid_limit`.'
x-error-codes:
- workspace_required
- invalid_filter
- invalid_limit
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: 'No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.'
x-error-codes:
- api_key_missing
- api_key_malformed
- api_key_unknown
- api_key_revoked
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: 'The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.'
x-error-codes:
- insufficient_scope
- subscription_inactive
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: 'Not found on this account. Codes: `workspace_not_found`, `account_not_found`.'
x-error-codes:
- workspace_not_found
- account_not_found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: 'Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.'
x-error-codes:
- rate_limit_burst
- rate_limit_daily
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: 'Something went wrong on our end. Codes: `internal_error`.'
x-error-codes:
- internal_error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
tags:
- Analytics
components:
schemas:
TikTokChoices:
type: object
description: 'With `tiktok_choices_needed`: what to put in front of the user before a TikTok post goes. Build the UI from it; never pick for the user.'
properties:
creator:
type: object
properties:
nickname:
type:
- string
- 'null'
avatarUrl:
type:
- string
- 'null'
privacyLevel:
type: object
description: 'No default: `default` is always null.'
properties:
default:
type: 'null'
options:
type: array
items:
type: object
properties:
value:
type: string
label:
type: string
notWithBrandedContent:
type: array
items:
type: string
interactions:
type: array
items:
type: object
properties:
key:
type: string
label:
type: string
default:
const: false
disabledByCreator:
type: boolean
commercialContent:
type: object
description: Off by default; once on, at least one of `yourBrand` / `brandedContent`, each with the label TikTok shows.
aiGenerated:
type: object
maxVideoPostDurationSec:
type:
- integer
- 'null'
videoDurationSec:
type: number
declaration:
type: object
description: 'Shown, with its links, and agreed to before `userConsented: true` is sent.'
properties:
text:
type: string
textWithBrandedContent:
type: string
links:
type: object
additionalProperties:
type: string
requiresConsent:
const: true
preview:
type: object
properties:
text:
type: string
mediaUrls:
type: array
items:
type: string
lastUsed:
type: object
description: 'The account''s last answers that still apply, when it has some: ask the user once, then send `{useLast: true, userConsented: true}`.'
properties:
settings:
type: object
summary:
type: string
nextStep:
type: string
PerformanceFindings:
type: object
description: 'With `findings`: what the window says, each a comparison of numbers in the report, with a floor below which it says there is not enough data. The same block MCP get_performance returns.'
properties:
timezone:
type: string
description: The workspace timezone the weekdays and hours are in.
comparison:
type: object
description: Per platform, this window against the preceding one of equal length. Reach is compared only when both windows count the same thing (`basis`).
properties:
previousFrom:
type:
- string
- 'null'
previousTo:
type:
- string
- 'null'
platforms:
type: array
items:
type: object
ranking:
type: object
description: 'The top and bottom three posts by engagement rate, and the traits most of the top ones share and fewer bottom ones do; `enoughData: false` under six rated posts.'
bestWindows:
type: array
items:
type: object
description: 'Per account: windows from its own posts, or labelled fallbacks when it has too few.'
followers:
type: array
items:
type: object
description: 'Per account: first and last measured follower count in the window.'
postAgainToday:
type: array
items:
type: object
description: 'Per account: posts in the last 24 hours, scheduled in the next 24, the usual count on posting days, and the daily cap.'
Error:
type: object
required:
- error
properties:
error:
type: object
required:
- type
- code
- message
properties:
type:
type: string
enum:
- authentication_error
- permission_error
- invalid_request_error
- rate_limit_error
- api_error
code:
type: string
description: Stable identifier to branch on. See /docs/api/errors.
message:
type: string
description: For a human reading a log; may change.
param:
type: string
description: The offending field, when one can be named.
tiktokChoices:
$ref: '#/components/schemas/TikTokChoices'
problems:
type: array
items:
type: object
properties:
field:
type: string
code:
type: string
message:
type: string
description: '`tiktok_choices_needed` after settings were sent: what was wrong with each.'
settingsUrl:
type: string
description: '`tiktok_choices_needed`: the post in the composer with its settings open.'
Performance:
type: object
required:
- object
- workspaceId
- window
- platforms
- rows
- rowCount
properties:
object:
const: performance
workspaceId:
type: string
window:
type: object
properties:
from:
type: string
to:
type: string
accounts:
type: array
items:
type: object
platforms:
type: array
items:
type: object
properties:
platform:
type: string
postCount:
type: integer
totals:
type: object
additionalProperties:
type:
- number
- 'null'
engagement:
type:
- number
- 'null'
rate:
type:
- number
- 'null'
skipped:
type: integer
syncedAt:
type:
- string
- 'null'
oldestAsOf:
type:
- string
- 'null'
rows:
type: array
items:
type: object
properties:
postId:
type: string
platform:
type: string
text:
type: string
publishedAt:
type:
- string
- 'null'
accountId:
type: string
campaignId:
type: string
goal:
type: string
description: The post's goal, when it has one.
metrics:
type: object
additionalProperties:
$ref: '#/components/schemas/MetricCell'
engagement:
type:
- number
- 'null'
rate:
type:
- number
- 'null'
degraded:
type: array
items:
type: string
rowCount:
type: integer
degradedRows:
type: integer
previous:
type: array
description: 'With `compare`: the platform totals over the preceding window.'
findings:
$ref: '#/components/schemas/PerformanceFindings'
EngagementHistory:
type: object
required:
- object
- schema
- rows
- rowCount
- workspaceId
- days
properties:
object:
const: engagement_history
schema:
type: object
description: Column names and BigQuery-style types (STRING, INTEGER, DATE, BOOL); every column is NULLABLE.
properties:
fields:
type: array
items:
type: object
properties:
name:
type: string
type:
type: string
mode:
const: NULLABLE
rows:
type: array
description: 'Workspace: date, platform (`all` for the day), likes, comments, shares, impressions, reachBasis, reach, saves, clicks, bookmarks, linkClicks, profileVisits, follows, watchTimeSeconds, degraded, awaitingPermission. Post: date, platform, cumulative* and daily* for each counter, spanDays, unreadableFields, awaitingPermission.'
items:
type: object
additionalProperties:
type:
- string
- number
- boolean
- 'null'
rowCount:
type: integer
workspaceId:
type: string
postId:
type: string
description: With `postId` only.
days:
type:
- integer
- 'null'
startDate:
type: string
format: date
endDate:
type: string
format: date
platforms:
type: array
items:
type: string
platformTotals:
type: object
additionalProperties:
type: object
additionalProperties:
type: number
rangeTotals:
type: object
additionalProperties:
type:
- number
- 'null'
followers:
type: object
description: 'A second table, one row per (date, account): date, accountId, accountName, platform, followers (null, never 0, when not counted), dailyChange, approximate, unavailableReason.'
message:
type: string
description: Present when there is no daily data yet.
MetricCell:
type: object
required:
- value
- state
properties:
value:
type:
- number
- 'null'
description: Null unless `state` is `measured`; never 0 for unknown.
state:
type: string
description: '`measured`, `unsupported` (the platform cannot supply it), `unreadable` (a carried-forward value), or not yet measured.'
basis:
type: string
reason:
type: string
asOf:
type: string
format: date-time
securitySchemes:
apiKey:
type: http
scheme: bearer
description: '`Authorization: Bearer ak_...`. See /docs/api/keys.'