OAuth v2 workflows
Installation
Section titled “Installation”npm install --global @anakonn/ankk@0.5.1ankk --versionSign in and choose a brand
Section titled “Sign in and choose a brand”ANKK v2 uses your user account through browser OAuth. Your existing permissions apply to every request. Connecting an app does not grant extra brand permissions. Choose a brand when working; OAuth authorization does not select a brand.
Use CLI 0.5.1 with Node.js 24 or newer. The public client ID below identifies ANKK CLI; it is not a secret.
export ANKK_OAUTH_CLIENT_ID=ankk-cli-productionankk --json auth login --environment productionankk auth status --environment production --connection OAUTH_CONNECTION_IDankk --json brands list --environment production --connection OAUTH_CONNECTION_ID --allankk --json connections list --environment production --connection OAUTH_CONNECTION_ID --brand BRAND_ID --allReplace uppercase identifiers with IDs returned by your own requests. The OAuth connection ID selects your login. An SNS account ID identifies a posting target; it is different from both the OAuth connection and the provider’s account ID. Use the same environment and brand throughout a workflow. These examples specify both explicitly even when you have configured a local brand default.
For a terminal without an automatically opened browser, use
ankk auth login --environment production --device --no-open and follow the displayed
verification instructions. Tokens are stored in the OS credential store. If that
store is unavailable, restore it before signing in; never paste tokens into a chat
or save them in a publication JSON file.
Read performance and stored posts
Section titled “Read performance and stored posts”ankk --json analytics get --environment production --connection OAUTH_CONNECTION_ID --brand BRAND_ID --from 2026-10-01T00:00:00Z --to 2026-10-02T00:00:00Zankk --json posts list --environment production --connection OAUTH_CONNECTION_ID --brand BRAND_ID --allChoose the actual reporting period. The start is inclusive and the end exclusive;
timestamps use UTC. Translate the user’s local dates into UTC before querying.
Add --sns-account SNS_ACCOUNT_ID to limit the result to one account.
The result describes stored observations. Check coverage and observation times
before comparing periods. Missing data is not zero. A latest account snapshot has
its own measurement time and is not necessarily a period total. Instagram exact
period insights are separate from accumulated observations. A read does not start
provider collection. posts refresh is a separate action for post/comment data,
not a request to refresh analytics.
Lists use cursors. --all follows pages; data can change while paging, so the result
is not a snapshot. If a cursor expires, report the incomplete result and start a
new listing deliberately rather than combining it silently with the old pages.
Prepare a file before publication
Section titled “Prepare a file before publication”ankk --json media create-upload --environment production --connection OAUTH_CONNECTION_ID --brand BRAND_ID --file ./photo.jpg --idempotency-key UPLOAD_KEYankk --json media complete-upload MEDIA_ID --environment production --connection OAUTH_CONNECTION_ID --brand BRAND_ID --idempotency-key INSPECTION_KEY --wait --wait-timeout 180ankk --json media get MEDIA_ID --environment production --connection OAUTH_CONNECTION_ID --brand BRAND_IDThe first command registers and transfers the file. Save its media ID even if the
transfer fails or the reply is uncertain. The second requests inspection; use the
media only when the final media status is ready. These steps do not publish.
Media can be reused within its brand. Upload separately for another brand.
If only the upload URL expires, use media refresh-upload MEDIA_ID with the same
environment, login and brand. The new URL does not extend the original business
deadline or replace the file. Different bytes require a new media upload. Treat
signed transfer URLs as credentials and keep them out of shared transcripts.
Clients without file transfer can use the returned browser progress URL, sign in
and select the file, then return with the same media ID and check readiness.
Review and publish
Section titled “Review and publish”Confirm the brand, accounts, full text, ordered thread segments, attachments, provider options and execution time before publishing AI-prepared content. Existing approval for the exact intent is sufficient. A request to analyze or draft content alone is not publication approval.
Save this minimal immediate-publication input as publish.json. Select an account
that supports the proposed text-and-image combination; the server checks current
capability, media readiness and permission again.
{ "scheduled_at": null, "targets": [ { "sns_account_id": "SNS_ACCOUNT_ID", "text": "The exact text you approved", "media_ids": ["MEDIA_ID"] } ]}ankk --json contents publish --environment production --connection OAUTH_CONNECTION_ID --brand BRAND_ID --file publish.json --idempotency-key PUBLICATION_KEYChoose and retain a unique key for this intent before sending. Reuse that exact key and payload after an uncertain response, including when moving between API, CLI and MCP. Do not create another publication just because a connection timed out. The same key with changed input is a conflict. An expired key does not create new work: inspect the old outcome before deliberately starting a new intent.
For a reservation, replace scheduled_at: null with the approved future UTC time,
for example 2026-12-01T09:00:00Z. Replace this illustrative date before use and
verify it is still in the future. A completed registration returns a separate
publish_operation_id; it does not mean the scheduled SNS posts are published.
Follow the outcome
Section titled “Follow the outcome”ankk --json operations get OPERATION_ID --environment production --connection OAUTH_CONNECTION_ID --brand BRAND_ID --wait --wait-timeout 180For immediate publication, follow the returned operation ID. For a reservation,
follow publish_operation_id at execution time. Waiting is optional and local.
CLI exit 10 means the wait limit expired; exit 130 means waiting was interrupted.
Neither cancels the server task. Continue reading the same operation. Exit 11 from
waiting indicates a failed, canceled or partially successful final outcome;
inspect the per-account results. A normal status lookup can exit 0 while reporting
a failed operation, so scripts must inspect the response status too.
Report each account separately. Preserve successful posts and their URLs. The
ordered posts array contains the confirmed posts of a thread; representative
post_url alone may not describe the whole thread. An absent URL or unresolved
status is not proof that the provider created nothing. Keep reconciling and unknown
outcomes unresolved until the existing task supplies evidence.
Change a reservation or recover a failure
Section titled “Change a reservation or recover a failure”Read contents get CONTENT_ID with the same environment, login and brand before
changing content or time. Pass its current version as --expected-version.
contents update edits eligible unstarted targets; contents reschedule changes
their UTC schedule. A version conflict requires a new read and review, not a
silent overwrite. contents cancel requests cancellation; inspect the returned
publication operation until cancellation is confirmed. Execution may win the race.
Retry only selected failed accounts currently marked can_retry:
ankk --json contents retry ORIGINAL_OPERATION_ID --environment production --connection OAUTH_CONNECTION_ID --brand BRAND_ID --accounts FAILED_SNS_ACCOUNT_ID --idempotency-key RETRY_KEYThis is a new execution intent and needs an appropriate new key and user approval
unless already covered. Keep that retry key after an uncertain response. Retry
uses stored content and executes as soon as possible; it never republishes successful
or uncertain targets. For a new future reservation, contents duplicate returns
editable input only. Review it and submit a new approved publication.
Discarding eligible failed queue entries hides them from the work queue; it does not delete posts, erase execution history or retry anything. Bulk cancellation can return accepted and rejected groups together; follow each accepted publication operation. Bulk discard completes synchronously: inspect the receipt’s discarded and rejected groups, without waiting for a new operation. In both cases, read the complete receipt instead of treating an exit code as an all-or-nothing result.
Handle request errors and disconnect
Section titled “Handle request errors and disconnect”Read the structured error code, request ID, operation ID when available,
next_action and retry_at. Authentication recovery returns to the original
operation. Permission errors require legitimate access, not a different interface.
Rate limits and capability restrictions must be respected. A retryable request
does not authorize a new publication or replacement key.
ankk auth logout --environment production --connection OAUTH_CONNECTION_IDLogout reports server revocation separately from local credential removal. If server revocation is unconfirmed, revoke the old connection from ANKK settings or another valid connection. Removing an OAuth connection does not cancel already accepted publications or delete brand-owned media.
Use MCP and Skills
Section titled “Use MCP and Skills”MCP uses user OAuth at https://api.ankk.app/mcp/v2. Your host needs a registered client; an endpoint URL alone does not complete setup. Official ChatGPT and Claude directory listings are not available. Use text and structured results when cards are unavailable; verify analytics values and observation times rather than relying only on the conversational summary.
Skills provide procedures, not permissions or credentials. Install the pinned release candidate below. Verify the selected brand, approval and final operation result.
npx skills add https://github.com/Anakonn/ankk-skills/tree/v0.1.0-rc.1 --skill ankk-analyze --skill ankk-publish