# Nonli Developer API > API documentation for clients and AI agents integrating with Nonli. Base URL: https://api.nonli.com/v2.1 OpenAPI: https://www.nonli.com/api-docs/openapi.json Human documentation: https://www.nonli.com/en/developers Authentication: - Create an API token from the Nonli back office. - Send it on authenticated calls using Authorization: Bearer YOUR_API_TOKEN. - API tokens represent a company role, not a web user session. Do not use /me with Bearer tokens. - To validate a token, call GET /brands?size=1&fields=id,name. Common query grammar: - filters uses semicolon-separated AND filters, for example filters=brandId:1;status:200. - filtersOr uses OR values, for example filtersOr=status:200,203. - ranges use two dots, for example publishedAt:2024-05-01T00:00:00Z..2024-05-31T23:59:59Z. - Send the filter separators (colon, semicolon, comma, double dot) as raw characters. Search endpoints read the raw query string, so percent-encoded separators such as %3A are treated as literal value characters and the filter silently matches nothing or returns 400. Percent-encode only characters inside values, such as spaces (%20). - fields limits returned fields and should be used by agents to reduce payload size. - Post-backed endpoints accept the documented post counters in counter filters and counter sorts. Historical counter names replaced by public counter names are intentionally omitted. - Organic Listening, Shortlink, and Accounts endpoints expose their own standard counters and reject post counters. - The leaderboard aggregationField accepts the documented post counter names; the API resolves them to stored counters internally. Available standard counters: - Posts, Social Listening, and Bots (/posts, /posts/categories, /posts/brands, /posts/users, /posts/languages, /posts/histogram, /posts/aggregation, /posts/stats, /posts/tags, /posts/topics, /posts/leaderboard, /posts/leaderboard/_search, /posts/leaderboard/categories, /listening/social, /bots/bulk): click, click_unique, ctr, engagement, facebook_engagement_per_minute, weighted_facebook_engagement, weighted_facebook_engagement_per_minute, facebook_comment, facebook_total_reaction, facebook_share, reach, impression, videoViews, video_views_3sec, facebook_post_video_avg_time_watched, video_completion_rate, overperforming, reposts, quotes, monetization, snapchat_screenshots, subscriber, facebook_link_clicks, facebook_other_clicks, facebook_photo_view, facebook_video_play, facebook_post_video_views_60s_excludes_shorter, instagram_saved, instagram_total_interactions, instagram_clips_replays_count, linkedin_private_click_count, youtube_likes, youtube_dislikes, youtube_estimated_minutes_watched. Use these names in post-backed counter filters, counter sorts, bot trigger counters, and bot post-rate metrics. Facebook reach is requested as `reach`; the API maps the current Meta reach metric internally. TikTok metrics currently feed the common post counters `engagement`, `facebook_total_reaction`, `facebook_comment`, `facebook_share`, `videoViews`, and `impression`, instead of dedicated TikTok counters. Historical counter names replaced by these public names, and counters that are no longer available from network APIs, are intentionally omitted. - Organic Listening (/listening/organic, /listening/organic/stats, /listening/organic/aggregation): click, new_lead, quantity, amount, paywall_view, paywall_unlocked, paywall_click, paywall_subscribe_click, paywall_login_click, subscription_complete, comment_count, video_views, view_in_stock, view_out_of_stock, price, price_variation, low_price, high_price, rating, review_count, stock. Use these names for standard Organic Listening counter filters and sorts. Legacy Organic counters are intentionally excluded from the public API surface. - Shortlinks (/shortlinks, /shortlinks/:shortlinkId, /shortlinks/stats, /shortlinks/authors, /shortlinks/brands): click. Shortlink counter endpoints only expose shortlink counters and reject post counters. - Accounts (/accounts, /accounts/stats): follower_count. Use the full counter path on Accounts endpoints, for example sort=-counters.total.follower_count or filters=counters.graph.counter:follower_count. The counter sort shorthand (sort=-follower_count) also resolves. The documented name is resolved to the stored account counter internally; historical internal counter names are intentionally omitted. Post counters such as engagement, reach, or videoViews are invalid for Accounts. Conventions: - Responses echo the counter names the request used: request counters by their documented public names (engagement, follower_count, ...) and counters come back under those names; request stored names and stored names come back. - List endpoints return total plus a rows array; page with size and a zero-based page until total items are collected. On GET /posts, size accepts 0 to 100 and (page + 1) × size cannot exceed 10,000 (400 Bad Request beyond); narrow the filters to reach older posts. - Timestamps are UTC ISO-8601, for example 2026-05-27T23:59:59Z. Dates in request bodies (createdAt, publishedAt, schedule.startDate, schedule.endDate) must be exactly YYYY-MM-DDTHH:MM:SSZ: fractional seconds or a UTC offset return 400, so remove milliseconds before sending back a date read from a response. On post and listening search endpoints, the upper bound of a date-range filter is excluded. - Rate limits are counted per company and per endpoint, shared by every API token of the company, in fixed windows that open with the first call; endpoints without a documented limit have no per-endpoint call limit. Limited endpoints return RateLimit-Limit and RateLimit-Remaining headers; after the limit every call returns 429 until the window closes, without a Retry-After header. GET /listening/social is counted against the company Social Listening pack instead, with no per-endpoint window and no RateLimit headers. - Post status: without a status value in the filters parameter (filtersOr does not count), GET /posts, /posts/aggregation, and /posts/histogram return or count every status except 404 (deleted) and 410 (outdated), including drafts, scheduled posts, posts awaiting review, and failed publications; GET /posts/stats applies no default status filter. For figures consistent with published content, add `filtersOr=status:200,203,204`: published, publishing, and waiting to retry, the statuses of the "Published" group in the Nonli back office. - Identifiers are string UUIDs for posts, shortlinks, and organic items, hash strings for listening accounts, and integers for brands, connected social accounts, and themes. - The API token is a bearer credential; store it securely, rotate it from the back office, and do not put it in query strings. Errors: - Branch on the HTTP status code rather than parsing error message text. - 400 bad request, 401 unauthorized (check or rotate the API token), 403 forbidden, 404 not found, 429 rate limited (back off and retry), 5xx server error. Core endpoints: - GET /brands: Search brands. Return the brands visible to the API token role in the authenticated company. - GET /brands/:brandId: Get a brand. Return one brand with optional embedded configuration used for publishing, shortlinks, smart images, and URL parameters. - GET /social-accounts: Search social accounts. Return social accounts available to the authenticated company and user. - GET /social-accounts/:socialAccountId: Get a social account. Return one connected social account with publishing metadata. - GET /social-accounts/publishing-quota: Get publishing quota. Return publishing quota information for selected social accounts before scheduling posts. - GET /social-accounts/youtube/playlists: Get YouTube playlists. Return the playlists of connected YouTube social accounts, to choose the `youtube.playlistIds` of a YouTube post. Playlist items (videos) are not returned. IDs that are not YouTube social accounts of your company are silently left out of the response. When YouTube rejects the request for one account, its entry has an empty `playlists` array and an `error` message, and the other accounts are still returned. Playlists are cached for one hour per account; set `force=true` to read them from YouTube again. - GET /social-accounts/pinterest/boards: Get Pinterest boards. Return the boards of connected Pinterest social accounts, to choose the `pinterest.boardId` of a Pinterest post. IDs that are not Pinterest social accounts of your company are silently left out of the response. When Pinterest rejects the request for one account, its `boards` array is empty. Boards are cached for one hour per account; set `force=true` to read them from Pinterest again. - GET /posts: Search posts. Search the posts of your company in any status other than deleted or outdated: drafts, scheduled, published, and failed posts, and posts imported from connected accounts. Post-backed endpoints accept the documented post counters in counter filters and counter sorts, and responses echo the counter names the request used. Historical counter names replaced by public counter names are intentionally omitted. Without a `status` value in `filters`, posts of every status except 404 (deleted) and 410 (outdated) are returned, including drafts, scheduled posts, posts awaiting review, and failed publications. For figures consistent with published content, add `filtersOr=status:200,203,204`: published, publishing, and waiting to retry, the statuses of the "Published" group in the Nonli back office. Set `withDeleted=true` to also return deleted and outdated posts. Post `status` values: 200 published, 201 draft, 202 scheduled, 203 publishing, 204 waiting to retry publication, 210 awaiting review, 404 deleted, 410 outdated, 500 error, 503 publication error, 504 deletion error. Other codes are internal transitional or error states. Posts that Nonli imports from connected accounts, because they were published directly on the network rather than through Nonli, have `userId` -5 and no `brandId`: a `brandId` filter leaves them out. Filter on `socialAccount.externalId` and `socialAccount.type` to include them. Rate limit: 720 calls every 12 hours per company and per endpoint, shared by all API tokens of the company. Each window opens with the first counted call. Creating or rotating a token neither resets nor extends the window; the 721st call in the window returns 429, and every later call returns 429 until the window closes. Each request counts as one call, whatever the number of items in a bulk request. - GET /posts/:postId: Get a post. Return one post by ID with optional filters and field selection. - GET /posts/categories: Get post categories. Return category aggregations used by post filters and dashboards. Post-backed endpoints accept the documented post counters in counter filters and counter sorts, and responses echo the counter names the request used. Historical counter names replaced by public counter names are intentionally omitted. Rate limit: 200 calls every 10 minutes per company and per endpoint, shared by all API tokens of the company. Each window opens with the first counted call. Creating or rotating a token neither resets nor extends the window; the 201st call in the window returns 429, and every later call returns 429 until the window closes. Each request counts as one call, whatever the number of items in a bulk request. - GET /posts/brands: Get post brands. Return brand aggregations for posts visible to the API token role. Post-backed endpoints accept the documented post counters in counter filters and counter sorts, and responses echo the counter names the request used. Historical counter names replaced by public counter names are intentionally omitted. Rate limit: 200 calls every 10 minutes per company and per endpoint, shared by all API tokens of the company. Each window opens with the first counted call. Creating or rotating a token neither resets nor extends the window; the 201st call in the window returns 429, and every later call returns 429 until the window closes. Each request counts as one call, whatever the number of items in a bulk request. - GET /posts/users: Get post users. Return user aggregations for post author and collaboration filters. Post-backed endpoints accept the documented post counters in counter filters and counter sorts, and responses echo the counter names the request used. Historical counter names replaced by public counter names are intentionally omitted. - GET /posts/languages: Get post languages. Return language aggregations for post filters. Post-backed endpoints accept the documented post counters in counter filters and counter sorts, and responses echo the counter names the request used. Historical counter names replaced by public counter names are intentionally omitted. Rate limit: 200 calls every 10 minutes per company and per endpoint, shared by all API tokens of the company. Each window opens with the first counted call. Creating or rotating a token neither resets nor extends the window; the 201st call in the window returns 429, and every later call returns 429 until the window closes. Each request counts as one call, whatever the number of items in a bulk request. - GET /posts/histogram: Get post histogram. Return time-bucketed post counts for graphing. Post-backed endpoints accept the documented post counters in counter filters and counter sorts, and responses echo the counter names the request used. Historical counter names replaced by public counter names are intentionally omitted. Without a `status` value in `filters`, posts of every status except 404 (deleted) and 410 (outdated) are counted, including drafts, scheduled posts, posts awaiting review, and failed publications. For figures consistent with published content, add `filtersOr=status:200,203,204`: published, publishing, and waiting to retry, the statuses of the "Published" group in the Nonli back office. - GET /posts/aggregation: Get post aggregation. Return generic aggregations for post dashboards and filter facets. Post-backed endpoints accept the documented post counters in counter filters and counter sorts, and responses echo the counter names the request used. Historical counter names replaced by public counter names are intentionally omitted. Without a `status` value in `filters`, posts of every status except 404 (deleted) and 410 (outdated) are counted, including drafts, scheduled posts, posts awaiting review, and failed publications. For figures consistent with published content, add `filtersOr=status:200,203,204`: published, publishing, and waiting to retry, the statuses of the "Published" group in the Nonli back office. - GET /posts/stats: Get post stats. Return aggregated post performance statistics for dashboard widgets. Post-backed endpoints accept the documented post counters in counter filters and counter sorts, and responses echo the counter names the request used. Historical counter names replaced by public counter names are intentionally omitted. This endpoint applies no default status filter: without a status filter, posts of every status are counted, including drafts, scheduled posts, failed publications, and deleted (404) or outdated (410) posts. For figures consistent with published content, add `filtersOr=status:200,203,204`: published, publishing, and waiting to retry, the statuses of the "Published" group in the Nonli back office. - POST /posts/check: Check post content. Validate post content before publishing. The BO uses this endpoint to surface publication warnings. - GET /posts/tags: Get post tags. Return the most used values of the post `tag` field that match a prefix, for autocomplete and reporting filters. Post-backed endpoints accept the documented post counters in counter filters and counter sorts, and responses echo the counter names the request used. Historical counter names replaced by public counter names are intentionally omitted. Only published posts (status 200) are counted. This endpoint aggregates the `tag` field, not `customTag`: tags written in `customTag` are not returned. To list the tags configured on a brand, read its `customTags` with GET /brands/:brandId?fields=id,name,customTags. Prefix matching is case-sensitive. Rate limit: 200 calls every 10 minutes per company and per endpoint, shared by all API tokens of the company. Each window opens with the first counted call. Creating or rotating a token neither resets nor extends the window; the 201st call in the window returns 429, and every later call returns 429 until the window closes. Each request counts as one call, whatever the number of items in a bulk request. - GET /posts/topics: Get post topics. Return the most used post topics that match a prefix, for autocomplete and reporting filters. Post-backed endpoints accept the documented post counters in counter filters and counter sorts, and responses echo the counter names the request used. Historical counter names replaced by public counter names are intentionally omitted. Only published posts (status 200) are counted. Prefix matching is case-sensitive. Rate limit: 200 calls every 10 minutes per company and per endpoint, shared by all API tokens of the company. Each window opens with the first counted call. Creating or rotating a token neither resets nor extends the window; the 201st call in the window returns 429, and every later call returns 429 until the window closes. Each request counts as one call, whatever the number of items in a bulk request. - POST /posts/bulk: Create posts in bulk. Create one or more posts as drafts, submit them for review, publish them immediately, or schedule them. The API-token role must grant `post.write` and access to every requested brand and social account. Post status is constrained by the API-token role. `review` always remains pending validation, and read access to the target is sufficient to create a post for review. A `publish` request is automatically downgraded to `review` when the role cannot publish directly. Tokens without `post.write` or access to the requested resources are rejected. The creator identity is server-managed. Posts created with a Bearer token use `API ` as `author` and have no `userId`. Client-supplied author identity fields are ignored, so an API integration cannot impersonate a Nonli user. Build a thread sequentially. Set `thread.activated=true` on every segment. The root omits `isChild`, `parent`, and `origin`; every later segment sets `isChild=true`, `parent` to the immediately previous segment ID, and `origin` to the root ID. For the first child, `parent` and `origin` therefore have the same root ID. After adding each child, read the root and verify its ordered `thread.children` list: a successful HTTP response alone does not prove that the chain is complete. On networks with first-comment support, put the article link in `post.comment`. Threads and Bluesky do not publish a native first comment, so a hand-built chain must instead attach the shortlink to the root with `shortlink.mappingId` and put the resolved public URL only in the final segment message. Create that final segment without the URL, update it with the root response values `https://ROOT_SHORT_DOMAIN/ROOT_SHORT_ID`, then read the root and final segment back before publication. Do not also place that URL in a root first comment. On Threads and Bluesky, Nonli can automatically convert an active first comment into the first child when the root has neither an activated thread nor existing children. `[SHORTLINK]` is expanded only during that conversion and only when the first comment has a shortlink. It is not expanded in segments created directly through `/posts/bulk`; hand-built segments must contain the resolved URL. Validate every segment against its destination network before creating the chain. Threads currently allows 500 characters per segment; Bluesky allows 300 graphemes. Mentions and links contribute to those limits, including the resolved shortlink added to the final segment. Rate limit: 200 calls every 10 minutes per company and per endpoint, shared by all API tokens of the company. Each window opens with the first counted call. Creating or rotating a token neither resets nor extends the window; the 201st call in the window returns 429, and every later call returns 429 until the window closes. Each request counts as one call, whatever the number of items in a bulk request. - PUT /posts/bulk: Update posts in bulk. Update a collection of posts. Send post.id and, when available, createdAt to optimize lookup. Send each post with `id`, its `createdAt` when known, and only the fields you change. `createdAt` locates the post and is never modified. Accepted post fields: socialAccount (externalId, publisherId, type, subType), brandId, tag, customTag, postType, subType, shortlink.mappingId, source.documentId, title, message, description, image, video, media, schedule (startDate, endDate), publishedAt, createdAt, breakingNews, callToAction, shortId, comment (activated, message, pictureUrl), status, isAiGenerated, sponsor, location, geoblocking.country, commentEnabled, duetEnabled, stitchEnabled, madeForKids, threads, visibility, collaborator, pinterest.boardId, youtube.playlistIds, commercialContent, and tiktok.anchor. Each `video` item accepts url, mappingId, embed, sourceExternalId, title, tag, thumbnail, shareToFeed, isAiGenerated, duration, height, width, and size. Any other key, at any level, makes the whole request fail with 400 Bad Request and an "Unexpected item(s)" message. This includes read-only fields returned by `GET /posts/:postId`, such as socialAccount fields other than externalId, publisherId, type, and subType, or `video[].externalId`: do not send back a post object read from the API unchanged. There is no maximum number of posts per call, and one call counts as one call against the rate limit whatever the number of posts. A very large batch can exceed the server time limits and fail, so split large batches into several calls. With `updatePostOnNetwork=false`, Nonli sends no update to the network for an already published post. A post that is not published yet stays in the publication scheduler, which publishes it at its scheduled date, or at its next run for a post sent without a schedule. Current exception: for a Facebook video post of a brand with Facebook crossposting enabled, Nonli may still prepare the crosspost video on Facebook during the call, and a missing video record makes the whole call fail. Rate limit: 200 calls every 10 minutes per company and per endpoint, shared by all API tokens of the company. Each window opens with the first counted call. Creating or rotating a token neither resets nor extends the window; the 201st call in the window returns 429, and every later call returns 429 until the window closes. Each request counts as one call, whatever the number of items in a bulk request. - DELETE /posts/bulk: Delete posts in bulk. Delete a collection of posts. The async flag can be used for background deletion. Rate limit: 100 calls every 10 minutes per company and per endpoint, shared by all API tokens of the company. Each window opens with the first counted call. Creating or rotating a token neither resets nor extends the window; the 101st call in the window returns 429, and every later call returns 429 until the window closes. Each request counts as one call, whatever the number of items in a bulk request. - GET /shortlinks: Search shortlinks. Search shortlinks and retrieve counters, target URLs, metadata, and publication information. Shortlink counter endpoints accept shortlink counters only, currently `click`. Post counters such as `engagement`, `reach`, or `videoViews` are invalid for Shortlinks. Rate limit: 720 calls every 12 hours per company and per endpoint, shared by all API tokens of the company. Each window opens with the first counted call. Creating or rotating a token neither resets nor extends the window; the 721st call in the window returns 429, and every later call returns 429 until the window closes. Each request counts as one call, whatever the number of items in a bulk request. - GET /shortlinks/:shortlinkId: Get a shortlink. Return one shortlink by ID with optional counters and field selection. Shortlink counter endpoints accept shortlink counters only, currently `click`. Post counters such as `engagement`, `reach`, or `videoViews` are invalid for Shortlinks. - GET /shortlinks/stats: Get shortlink stats. Return aggregated shortlink performance statistics. Shortlink counter endpoints accept shortlink counters only, currently `click`. Post counters such as `engagement`, `reach`, or `videoViews` are invalid for Shortlinks. - GET /shortlinks/authors: Get shortlink authors. Return author aggregations used by shortlink filters. Shortlink counter endpoints accept shortlink counters only, currently `click`. Post counters such as `engagement`, `reach`, or `videoViews` are invalid for Shortlinks. Rate limit: 200 calls every 10 minutes per company and per endpoint, shared by all API tokens of the company. Each window opens with the first counted call. Creating or rotating a token neither resets nor extends the window; the 201st call in the window returns 429, and every later call returns 429 until the window closes. Each request counts as one call, whatever the number of items in a bulk request. - GET /shortlinks/brands: Get shortlink brands. Return brand aggregations used by shortlink filters. Shortlink counter endpoints accept shortlink counters only, currently `click`. Post counters such as `engagement`, `reach`, or `videoViews` are invalid for Shortlinks. Rate limit: 200 calls every 10 minutes per company and per endpoint, shared by all API tokens of the company. Each window opens with the first counted call. Creating or rotating a token neither resets nor extends the window; the 201st call in the window returns 429, and every later call returns 429 until the window closes. Each request counts as one call, whatever the number of items in a bulk request. - POST /shortlinks: Create a shortlink. Create or extract a shortlink for a target URL. Rate limit: 200 calls every 10 minutes per company and per endpoint, shared by all API tokens of the company. Each window opens with the first counted call. Creating or rotating a token neither resets nor extends the window; the 201st call in the window returns 429, and every later call returns 429 until the window closes. Each request counts as one call, whatever the number of items in a bulk request. - POST /shortlinks/bulk: Create shortlinks in bulk. Create several shortlinks in one request. Rate limit: 200 calls every 10 minutes per company and per endpoint, shared by all API tokens of the company. Each window opens with the first counted call. Creating or rotating a token neither resets nor extends the window; the 201st call in the window returns 429, and every later call returns 429 until the window closes. Each request counts as one call, whatever the number of items in a bulk request. - PUT /shortlinks/:shortlinkId: Update a shortlink. Update target URL, metadata, images, brand association, and sponsor information for a shortlink. Rate limit: 200 calls every 10 minutes per company and per endpoint, shared by all API tokens of the company. Each window opens with the first counted call. Creating or rotating a token neither resets nor extends the window; the 201st call in the window returns 429, and every later call returns 429 until the window closes. Each request counts as one call, whatever the number of items in a bulk request. - POST /shortlinks/:shortlinkId/generate-message: Generate a message for a shortlink. Generate suggested social copy for a shortlink and content type. - GET /themes: Search themes. Return team, bot, or public themes visible to the API token role. Rate limit: 720 calls every 12 hours per company and per endpoint, shared by all API tokens of the company. Each window opens with the first counted call. Creating or rotating a token neither resets nor extends the window; the 721st call in the window returns 429, and every later call returns 429 until the window closes. Each request counts as one call, whatever the number of items in a bulk request. - GET /themes/:themeId: Get a theme. Return one saved theme by ID. - POST /themes: Create a theme. Create a saved theme. The API stores value and queryStrings as JSON-encoded strings and does not derive one from the other. Rate limit: 20 calls every 10 minutes per company and per endpoint, shared by all API tokens of the company. Each window opens with the first counted call. Creating or rotating a token neither resets nor extends the window; the 21st call in the window returns 429, and every later call returns 429 until the window closes. Each request counts as one call, whatever the number of items in a bulk request. - PUT /themes/:themeId: Update a theme. Update a saved theme. Every field is optional, so a partial update such as a rename alone is valid. When value changes, send the matching queryStrings because the API does not rebuild it automatically. Rate limit: 100 calls every 10 minutes per company and per endpoint, shared by all API tokens of the company. Each window opens with the first counted call. Creating or rotating a token neither resets nor extends the window; the 101st call in the window returns 429, and every later call returns 429 until the window closes. Each request counts as one call, whatever the number of items in a bulk request. - DELETE /themes/:themeId: Delete a theme. Delete a saved theme. Rate limit: 50 calls every 10 minutes per company and per endpoint, shared by all API tokens of the company. Each window opens with the first counted call. Creating or rotating a token neither resets nor extends the window; the 51st call in the window returns 429, and every later call returns 429 until the window closes. Each request counts as one call, whatever the number of items in a bulk request. - GET /themes/roles: Get theme roles. Return roles that can be associated with team-scoped themes. - GET /listening/social: Get social listening. Search social posts and counters collected from supported social networks. Post-backed endpoints accept the documented post counters in counter filters and counter sorts, and responses echo the counter names the request used. Historical counter names replaced by public counter names are intentionally omitted. Results cover only the social networks included in the company Social Listening plan: a filter on another network returns no results rather than an error. Rate limit: Counted against the company Social Listening (QUERY) pack instead of the per-company, per-endpoint API call limit. - GET /listening/organic: Get organic listening. Search website content indexed by Organic Listening. Organic Listening endpoints accept standard Organic Listening counters only. Post counters such as `engagement`, `reach`, or `videoViews` are invalid for Organic Listening and return 400 Bad Request. Rate limit: 720 calls every 12 hours per company and per endpoint, shared by all API tokens of the company. Each window opens with the first counted call. Creating or rotating a token neither resets nor extends the window; the 721st call in the window returns 429, and every later call returns 429 until the window closes. Each request counts as one call, whatever the number of items in a bulk request. - PUT /listening/organic: Upsert an organic with videos. Create or update an organic content item keyed by its normalized URL, together with its complete video association collection. Each video can carry its own thumbnail. The API-token role must grant `listening.write`. The `video` array is the complete association collection of the organic: associations omitted from the request are removed, and an empty array clears the collection. Already imported video assets survive in your company video library and are relinked automatically when a later request references the same `sourceId` or the same normalized video URL. Each video association must provide exactly one of `mappingId` (an already imported video asset of your company) or `url` (an external HTTPS video imported server-side). Video and thumbnail URLs must be HTTPS; they are fetched by the Nonli import pipeline, never by the browser. When at least one external video import is queued, the API returns 202 Accepted instead of 200. The response echoes each association with its import `state`: `linked` when the asset is already available, `queued` while the import runs, or `failed`. Rate limit: 300 calls every 10 minutes per company and per endpoint, shared by all API tokens of the company. Each window opens with the first counted call. Creating or rotating a token neither resets nor extends the window; the 301st call in the window returns 429, and every later call returns 429 until the window closes. Each request counts as one call, whatever the number of items in a bulk request. - GET /listening/organic/:organicId: Get organic content. Return one indexed organic content item by ID. - GET /listening/organic/stats: Get organic stats. Return aggregated Organic Listening performance statistics. Organic Listening endpoints accept standard Organic Listening counters only. Post counters such as `engagement`, `reach`, or `videoViews` are invalid for Organic Listening and return 400 Bad Request. - GET /listening/organic/aggregation: Get organic aggregation. Return generic aggregations for Organic Listening dashboards and filters. Organic Listening endpoints accept standard Organic Listening counters only. Post counters such as `engagement`, `reach`, or `videoViews` are invalid for Organic Listening and return 400 Bad Request. - GET /listening/organic/suggest/:field: Suggest organic filter values. Return autocomplete suggestions for an Organic Listening field. - GET /posts/leaderboard: Get the leaderboard. Return social accounts ranked by an aggregated post counter, with per post type breakdowns and account profile data. aggregationField and additionalAggregationFields accept the documented post counter names, such as engagement, reach, videoViews, click, ctr, overperforming, or monetization. The API resolves each documented name to the stored counter internally; historical internal counter names are intentionally undocumented. Counters built from public network data, such as engagement or videoViews, rank any listened account. Counters that require account ownership automatically restrict the leaderboard to social accounts the API token can access. Leaderboard filters and sorts accept the shorthand fields name, slug, category, and verificationStatus, resolved to the matching socialAccount fields internally. - POST /posts/leaderboard/_search: Search the leaderboard. Same ranking as GET /posts/leaderboard with parameters sent in the JSON body. Use it when the filter set exceeds URL length limits, for example large theme filters. aggregationField and additionalAggregationFields accept the documented post counter names, such as engagement, reach, videoViews, click, ctr, overperforming, or monetization. The API resolves each documented name to the stored counter internally; historical internal counter names are intentionally undocumented. Counters built from public network data, such as engagement or videoViews, rank any listened account. Counters that require account ownership automatically restrict the leaderboard to social accounts the API token can access. Leaderboard filters and sorts accept the shorthand fields name, slug, category, and verificationStatus, resolved to the matching socialAccount fields internally. - GET /posts/leaderboard/categories: Get leaderboard categories. Return the per post type counter breakdown for selected leaderboard accounts. aggregationField and additionalAggregationFields accept the documented post counter names, such as engagement, reach, videoViews, click, ctr, overperforming, or monetization. The API resolves each documented name to the stored counter internally; historical internal counter names are intentionally undocumented. - GET /accounts: Search accounts. Search social accounts tracked by Social Listening, with profile data and account counters. Accounts endpoints expose account counters only, currently follower_count (account fans or followers). The API resolves this documented name to the stored account counter internally, and responses echo the name the request used. Address it with the full counter path, for example sort=-counters.total.follower_count or filters=counters.graph.counter:follower_count. Post counters such as engagement or reach are invalid for Accounts. The category filter and query field resolve to the localized account category internally; filter with category: rather than a localized field path. - POST /accounts: Add an account. Add a social account to Social Listening. The account is fetched from the network, activated for listening, and returned. Requires a role with the listening manage permission. - GET /accounts/categories: Get account categories. Return account category aggregations for autocomplete and listening filters. The category filter and query field resolve to the localized account category internally; filter with category: rather than a localized field path. Rate limit: 200 calls every 10 minutes per company and per endpoint, shared by all API tokens of the company. Each window opens with the first counted call. Creating or rotating a token neither resets nor extends the window; the 201st call in the window returns 429, and every later call returns 429 until the window closes. Each request counts as one call, whatever the number of items in a bulk request. - GET /accounts/locations: Search account locations. Return location accounts, such as city pages, matching a query. Local index results are combined with a remote network search. A type filter selecting the social network is required. - GET /accounts/stats: Get account stats. Return aggregated account counter statistics with optional trend and histogram data. Accounts endpoints expose account counters only, currently follower_count (account fans or followers). The API resolves this documented name to the stored account counter internally, and responses echo the name the request used. Address it with the full counter path, for example sort=-counters.total.follower_count or filters=counters.graph.counter:follower_count. Post counters such as engagement or reach are invalid for Accounts. - GET /bots: Search bots. Return bots visible to the API token role in the authenticated company. - GET /bots/:botId: Get a bot. Return one bot by UUID. - POST /bots/bulk: Create bots in bulk. Create one or more bots. Source and target URNs must reference resources visible to the API token role. Bot trigger counters and post-rate metrics use the documented post counters. Percentile-based triggers resolve the documented counter name before calculating the percentile. The creator identity is server-managed. Bots created with a Bearer token use `API ` as `creatorName` and have no `creatorUserId`. Client-supplied creator identity fields are ignored, so an API integration cannot impersonate a Nonli user. - PUT /bots/bulk: Update bots in bulk. Update one or more bots. Each item must include the bot UUID and only the fields to change. Bot trigger counters and post-rate metrics use the documented post counters. Percentile-based triggers resolve the documented counter name before calculating the percentile. - DELETE /bots/:botId: Delete a bot. Delete one bot by UUID. A successful deletion returns HTTP 204 with no response body. - GET /bots/info: Get bot configuration info. Return schedule periods, target validation rules, and bot configuration constraints used to build valid bot payloads. - GET /media: Search media. Return media items available to the current company and user. - GET /media/tags: Get media tags. Return media tags for autocomplete and asset filtering. - POST /upload/image: Upload an image. Upload a base64 image and receive the Fontan slug used by posts and shortlinks. - POST /upload/video/token: Create upload video token. Create or resume an upload session. The response includes chunkSize, which defines the maximum chunk size to send. - POST /upload/video/exists: Check uploaded video existence. Check if a video already exists before starting a chunked upload. - POST /upload/video/chunk: Upload video chunk. Upload one base64 chunk for a video upload session. The final response includes the video id and URL. - POST /upload/document/token: Create upload document token. Create or resume a document upload session. The response includes chunkSize for chunked upload. - POST /upload/document/chunk: Upload document chunk. Upload one base64 chunk for a document upload session. The final response includes the document id and URL. Recommended agent flow: load the Bearer token from a secret store, request only needed fields, page through results with size/page, and respect rate limits.