API Reference

OneSocial API

One REST API (and a parity MCP server at /api/mcp) to connect social accounts, schedule/publish posts, track analytics, manage a unified inbox (comments/mentions/reviews/DMs), maintain a contacts CRM with custom fields, run broadcasts/sequences/comment-to-DM automations, and run a paid Ads Manager (ad accounts, campaigns, ads, audiences, tracking tags) across Meta, Google, TikTok, LinkedIn, Pinterest, and X. All endpoints are versioned under /api/v1 (except the D1 media file server at /api/v1/media/file/{tenantId}/{filename}, which is a plain unauthenticated static-file GET), authenticate via an `sk_`-prefixed API key as an HTTP Bearer token, and respond with the envelope `{ data }` for single resources or `{ data, page, limit, total }` for lists. Errors are `{ error: { code, message } }` with a matching HTTP status. Scopes are a closed allowlist (see `@/lib/scopes`): a key needs the exact scope string for an action (or `*`/`admin` for full access) — an empty scopes array grants nothing. A handful of read endpoints (comments, mentions, reviews, broadcasts, sequences, automations lists) do not yet enforce their `:read` scope — any authenticated key can call them; this is called out per-operation below. Ad-network credentials are entirely optional server-side config (`<NETWORK>_ADS_*` env vars); every Ads Manager endpoint is fully exercisable with zero ad-network credentials configured — unconfigured live calls fail closed and the local DB state is persisted regardless (see the AdAccounts/Ads/AdCampaigns/AdAudiences/TrackingTags operations below for specifics).

Authentication

Every request carries your API key as an HTTP Bearer token. Mint one from the dashboard or POST /api/v1/api-keys — the raw sk_ value is shown exactly once. Responses are always { data } (or { data, page, limit, total } for lists); errors are { error: { code, message } }.

curl /api/v1/user \
  -H "Authorization: Bearer sk_live_..."

Prefer an AI agent? The same operations are exposed as MCP tools at /api/mcp (JSON-RPC over HTTP, same Bearer key) — REST and MCP call identical server-side logic, so behavior never diverges.

Profiles

5 endpoints

Per-tenant containers for accounts and queue slots.

  • get/api/v1/profiles

    List profiles

  • post/api/v1/profiles

    Create a profile

    Requires scope `profiles:write`.

  • get/api/v1/profiles/{id}

    Get a profile

  • patch/api/v1/profiles/{id}

    Update a profile

    Requires scope `profiles:write`.

  • delete/api/v1/profiles/{id}

    Delete a profile

    Requires scope `profiles:write`. Cascades to the profile's accounts and queue slots.

Accounts

10 endpoints

Connected social accounts and account groups.

  • get/api/v1/accounts

    List accounts

    Accounts are created via the connect flow, not directly.

  • get/api/v1/accounts/{id}

    Get an account

  • patch/api/v1/accounts/{id}

    Update an account

    Requires scope `accounts:write`.

  • delete/api/v1/accounts/{id}

    Disconnect an account

    Requires scope `accounts:write`. Soft-disconnect: clears stored credentials and flips status to disconnected; PostTarget history is preserved.

  • get/api/v1/accounts/{id}/health

    Get account health

    DB-derived health snapshot (does not make a live call to the platform): connection status, whether we still hold encrypted credentials, and the last recorded error.

  • get/api/v1/account-groups

    List account groups

  • post/api/v1/account-groups

    Create an account group

    Requires scope `account-groups:write`. Bundles accounts under a profile for bulk targeting.

  • get/api/v1/account-groups/{id}

    Get an account group

  • patch/api/v1/account-groups/{id}

    Update an account group

    Requires scope `account-groups:write`.

  • delete/api/v1/account-groups/{id}

    Delete an account group

    Requires scope `account-groups:write`.

Connect

3 endpoints

OAuth and direct-credential flows for connecting an account to a platform.

  • post/api/v1/connect/authorize

    Start connecting an account

    Requires scope `accounts:connect`. For platform=mastodon this dynamically registers an OAuth app with the given instance and returns a real authUrl; for every other platform it returns mode='manual' with the fields to collect and POST to /connect/manual.

  • post/api/v1/connect/manual

    Connect an account with direct credentials

    Requires scope `accounts:connect`. Bypasses OAuth: validates the given credentials via the platform's PublisherAdapter.connectAccount() and persists them AES-256-GCM encrypted. Upserts on (tenantId, profileId, platform, platformAccountId).

  • get/api/v1/connect/callback

    Mastodon OAuth callback

    Redirect target for the Mastodon OAuth flow started by POST /connect/authorize. Not called with a Bearer sk_ key — tenant/profile authorization is instead proven by successfully decrypting the `state` query param, which was minted server-side after the original caller passed authenticate()+requireScope('accounts:connect').

    no api key

Posts

7 endpoints

Create, schedule, publish, and retry posts across platforms.

  • get/api/v1/posts

    List posts

  • post/api/v1/posts

    Create (and optionally schedule/publish) a post

    Requires scope `posts:write`. One PostTarget is created per accountId. If `publishNow` is true the post is claimed by the next cron tick immediately; if `scheduledFor` is set it publishes at that time; otherwise it is saved as a draft. Publishing always goes through the scheduler (claimDuePosts/publishPost) — never directly through adapters.

  • get/api/v1/posts/{id}

    Get a post

  • patch/api/v1/posts/{id}

    Update a post

    Requires scope `posts:write`. Only posts in status draft or scheduled may be updated.

  • delete/api/v1/posts/{id}

    Delete a post

    Requires scope `posts:write`. Cascades to its PostTarget and PostMedia rows.

  • post/api/v1/posts/{id}/retry

    Retry a post's failed targets

    Requires scope `posts:write`. Calls retryPost() from the scheduler — only re-attempts PostTarget rows currently in status failed; published targets are never re-sent.

  • post/api/v1/posts/validate

    Pre-flight validate content against target platforms

    Any authenticated API key (no extra scope). Read-only: reports whether `content` fits each target platform's character limit and whether the referenced `accountId`s are valid/connected, without creating anything.

Queue

6 endpoints

Recurring auto-schedule slots.

  • get/api/v1/queue

    List queue slots

  • post/api/v1/queue

    Create a queue slot

    Requires scope `queue:write`.

  • get/api/v1/queue/preview

    Preview upcoming queue slot occurrences

    Any authenticated API key (no extra scope). Read-only projection of a profile's enabled QueueSlots into their next N upcoming UTC occurrences; does not read or write any Post.

  • get/api/v1/queue/{id}

    Get a queue slot

  • patch/api/v1/queue/{id}

    Update a queue slot

    Requires scope `queue:write`.

  • delete/api/v1/queue/{id}

    Delete a queue slot

    Requires scope `queue:write`.

Media

4 endpoints

Pass-through media storage (no transcoding).

  • post/api/v1/media/upload

    Upload media

    Requires scope `media:write`. Accepts multipart/form-data (field `file`) or a JSON body with `url` (fetched pass-through and re-hosted) or `dataBase64`. Bytes are stored as-is — no transcoding. 25MB max.

  • post/api/v1/media/presign

    Pre-negotiate an upload slot

    Requires scope `media:write`. Returns a short-lived, tenant-bound token plus the URL/method/field name to POST bytes to (currently /v1/media/upload — swappable for a real object-storage presigned URL later without changing callers).

  • post/api/v1/validate/media-url

    Validate a remote media URL

    Read-only pre-flight check (any valid API key, no extra scope): confirms the URL is reachable, resolves its mime type/size, without downloading or storing it.

  • get/api/v1/media/file/{tenantId}/{filename}

    Serve an uploaded media file from disk

    Not bearer-authenticated on purpose — URLs returned by POST /v1/media/upload are embedded directly in outbound posts/DMs and rendered in <img>/<video> tags, so they must be fetchable by browsers and third-party platforms that can't attach an Authorization header. Access control relies on `filename` being an unguessable random UUID. Storage lives outside `public/` (fixes uploaded media 404ing under `next start`); both path segments are validated against a strict filesystem-safe pattern and resolved against the uploads root, rejecting any traversal attempt. Content-Type is derived from a small extension allowlist (falls back to application/octet-stream); responses always carry X-Content-Type-Options: nosniff and a restrictive Content-Security-Policy. Returns 404 (never 403) on a miss or a rejected/malformed path, so the endpoint never reveals filesystem shape.

    no api key

Webhooks

7 endpoints

Outbound event subscriptions and delivery history.

  • get/api/v1/webhooks

    List webhooks

  • post/api/v1/webhooks

    Create a webhook

    Requires scope `webhooks:write`. The response is the ONLY place `secret` (used to compute X-OneSocial-Signature) is ever returned.

  • get/api/v1/webhooks/{id}

    Get a webhook

  • patch/api/v1/webhooks/{id}

    Update a webhook

    Requires scope `webhooks:write`.

  • delete/api/v1/webhooks/{id}

    Delete a webhook

    Requires scope `webhooks:write`.

  • get/api/v1/webhooks/{id}/logs

    List a webhook's delivery history

  • post/api/v1/webhooks/test

    Send a test delivery

    Requires scope `webhooks:write`. Sends a one-off `webhook.test` delivery to the given webhook regardless of its subscribed events list.

ApiKeys

3 endpoints

sk_ API key lifecycle.

  • get/api/v1/api-keys

    List API keys

  • post/api/v1/api-keys

    Create an API key

    Requires scope `api-keys:write`. The raw sk_ value is returned ONCE in this response and is never retrievable again.

  • delete/api/v1/api-keys/{id}

    Revoke an API key

    Requires scope `api-keys:write`. Sets revokedAt; the key immediately stops authenticating.

User

1 endpoints

The currently authenticated actor.

  • get/api/v1/user

    Get the current actor

    Returns the tenant and API key identity behind the bearer sk_ token used on this request.

Usage

1 endpoints

Per-tenant usage counters.

  • get/api/v1/usage

    Get usage summary

    Account and post counters for the authenticated tenant. `from`/`to` default to the current UTC calendar month.

Analytics

3 endpoints

Per-day post/account metric rollups, daily series, and best-time-to-post suggestions.

  • get/api/v1/analytics

    Get an analytics rollup

    Requires scope `analytics:read`. Sums the typed PostMetric counters across `since`/`until` (default: trailing 30 days).

  • get/api/v1/analytics/daily

    Get analytics grouped by day

    Requires scope `analytics:read`. Same filters as GET /analytics, grouped by PostMetric.date for charting.

  • get/api/v1/analytics/best-time

    Get the best time to post

    Requires scope `analytics:read`. Buckets PostMetric rows by weekday x hour and ranks by engagement, to suggest optimal posting slots.

Comments

4 endpoints

Inbound comments on connected accounts' native posts, and replies to them.

  • get/api/v1/comments

    List comments

    Any authenticated API key (read-scope enforcement not yet applied to this endpoint).

  • get/api/v1/comments/{id}

    Get a comment

    Includes its threaded replies (Comment rows with parentId set) as `replies`, oldest first.

  • delete/api/v1/comments/{id}

    Delete/hide a comment

    Requires scope `comments:write`. Marks the comment status = deleted; does not remove the row.

  • post/api/v1/comments/{id}/reply

    Reply to a comment

    Requires scope `comments:write`. Persists the reply as a new Comment row (isOwn=true, parentId set to the original), flips the original's status to replied, and dispatches `comment.replied`. 409 if the original comment is already status=deleted.

Mentions

1 endpoints

Inbound @-mentions across connected accounts.

  • get/api/v1/mentions

    List mentions

    Any authenticated API key (read-scope enforcement not yet applied to this endpoint). Read-only — mentions have no reply concept.

Reviews

3 endpoints

Platform reviews (e.g. Google Business style) and replies to them.

  • get/api/v1/reviews

    List reviews

    Any authenticated API key (read-scope enforcement not yet applied to this endpoint).

  • get/api/v1/reviews/{id}

    Get a review

    Any authenticated API key (read-scope enforcement not yet applied to this endpoint).

  • post/api/v1/reviews/{id}/reply

    Reply to a review

    Requires scope `reviews:write`. Sets reply/repliedAt and status=replied, and dispatches `review.replied`. Re-posting to an already-replied review overwrites the stored reply (edit-in-place; there is a single `reply` field, not a thread).

Messages

6 endpoints

DM conversations and messages across connected accounts.

  • get/api/v1/messages

    List conversations

    Requires scope `messages:read`. Despite the path, this lists Conversation rows (message threads), sorted by lastMessageAt.

  • get/api/v1/conversations/{id}

    Get a conversation

    Requires scope `messages:read`. Includes its messages, oldest first.

  • post/api/v1/conversations/{id}/mark-read

    Mark a conversation read

    Requires scope `messages:write`. Sets unreadCount=0 and isRead=true on its inbound messages.

  • post/api/v1/messages/send

    Send a DM

    Requires scope `messages:write`. Sends via the platform adapter and records an outbound Message; pass `conversationId` to append to an existing thread, or `accountId`+`contactId` to start a new one.

  • patch/api/v1/messages/{id}

    Edit a message

    Requires scope `messages:write`. Only own outbound messages may be edited; sets editedAt.

  • delete/api/v1/messages/{id}

    Delete a message

    Requires scope `messages:write`. Soft-delete: sets deletedAt and status=deleted; thread ordering is preserved.

Contacts

7 endpoints

CRM contact records, their channels, and bulk import.

  • get/api/v1/contacts

    List contacts

    Requires scope `contacts:read`.

  • post/api/v1/contacts

    Create a contact

    Requires scope `contacts:write`. `customFields` is validated against this tenant's CustomFieldDef rows via validateCustomFields() before persistence.

  • post/api/v1/contacts/bulk-create

    Bulk-create contacts

    Requires scope `contacts:write`. Up to 1000 contacts per call; each is validated (including customFields) before a single createMany.

  • get/api/v1/contacts/{id}

    Get a contact

    Requires scope `contacts:read`. Includes channels.

  • patch/api/v1/contacts/{id}

    Update a contact

    Requires scope `contacts:write`. `customFields`, if present, is re-validated in full against this tenant's CustomFieldDef rows.

  • delete/api/v1/contacts/{id}

    Delete a contact

    Requires scope `contacts:write`. Cascades to its channels, broadcast recipient rows, and sequence enrollments.

  • post/api/v1/contacts/{id}/channels

    Add a channel to a contact

    Requires scope `contacts:write`. Rejects with 409 if this exact (platform, externalId) is already attached to the contact — unique per (contactId, platform, externalId).

CustomFields

5 endpoints

Tenant-defined custom field schemas for Contact.customFields.

  • get/api/v1/custom-fields

    List custom field definitions

    Requires scope `custom-fields:read`.

  • post/api/v1/custom-fields

    Create a custom field definition

    Requires scope `custom-fields:write`. Unique per tenant on `key`; 409 if that key already exists.

  • get/api/v1/custom-fields/{id}

    Get a custom field definition

    Requires scope `custom-fields:read`.

  • patch/api/v1/custom-fields/{id}

    Update a custom field definition

    Requires scope `custom-fields:write`.

  • delete/api/v1/custom-fields/{id}

    Delete a custom field definition

    Requires scope `custom-fields:write`. Does not retroactively strip the key from existing Contact.customFields JSON.

Broadcasts

7 endpoints

One-shot campaign messages sent to many contacts.

  • get/api/v1/broadcasts

    List broadcasts

    Any authenticated API key (read-scope enforcement not yet applied to this endpoint).

  • post/api/v1/broadcasts

    Create a broadcast

    Requires scope `broadcasts:write`. Created in status=draft (or scheduled, when `scheduledFor` is given); optionally seeds BroadcastRecipient rows from `contactIds`.

  • get/api/v1/broadcasts/{id}

    Get a broadcast

    Any authenticated API key (read-scope enforcement not yet applied to this endpoint). Includes its recipients.

  • patch/api/v1/broadcasts/{id}

    Update a broadcast

    Requires scope `broadcasts:write`. Only broadcasts in status draft or scheduled may be updated. Passing `contactIds` deletes all existing BroadcastRecipient rows for this broadcast and re-creates them (there is no separate add-recipients endpoint).

  • delete/api/v1/broadcasts/{id}

    Cancel a broadcast

    Requires scope `broadcasts:write`. Despite the HTTP method this does NOT delete the row: only broadcasts in status draft or scheduled may be cancelled; it marks their pending BroadcastRecipient rows status=skipped and sets the broadcast status=cancelled. There is no separate /cancel endpoint.

  • post/api/v1/broadcasts/{id}/send

    Send a broadcast now

    Requires scope `broadcasts:write`. Sets status=sending for the /api/cron/engage broadcasts pass to pick up immediately.

  • post/api/v1/broadcasts/{id}/schedule

    Schedule a broadcast

    Requires scope `broadcasts:write`. Sets status=scheduled and scheduledFor for the cron pass to claim once due.

Sequences

6 endpoints

Multi-step drip campaigns with delay/message/broadcast steps.

  • get/api/v1/sequences

    List sequences

    Any authenticated API key (read-scope enforcement not yet applied to this endpoint).

  • post/api/v1/sequences

    Create a sequence

    Requires scope `sequences:write`. Created in status=draft (unless `status` is given) with the given inline `steps` (defaults to an empty array).

  • get/api/v1/sequences/{id}

    Get a sequence

    Any authenticated API key (read-scope enforcement not yet applied to this endpoint).

  • patch/api/v1/sequences/{id}

    Update a sequence

    Requires scope `sequences:write`. Sets `status` to active/paused/draft here — there are no separate activate/pause endpoints.

  • delete/api/v1/sequences/{id}

    Delete a sequence

    Requires scope `sequences:write`. Hard-deletes the row (there is no cancelled status for sequences); rejected with 409 while any enrollment is still status=active.

  • post/api/v1/sequences/{id}/enroll

    Enroll a contact in a sequence

    Requires scope `sequences:write`. Upserts a single SequenceEnrollment row on (sequenceId, contactId) with status=active, currentStep=0, and nextRunAt derived from the first step. There is no separate unenroll endpoint or bulk form — call this once per contactId, and set the enrollment's status via a client-side record if you need to track unenrollment (the API itself has no route for it yet).

Automations

6 endpoints

Comment-to-DM automation rules and their trigger logs.

  • get/api/v1/automations/comment-to-dm

    List comment-to-DM automations

    Any authenticated API key (read-scope enforcement not yet applied to this endpoint).

  • post/api/v1/automations/comment-to-dm

    Create a comment-to-DM automation

    Requires scope `automations:write`.

  • get/api/v1/automations/comment-to-dm/{id}

    Get a comment-to-DM automation

    Any authenticated API key (read-scope enforcement not yet applied to this endpoint).

  • patch/api/v1/automations/comment-to-dm/{id}

    Update a comment-to-DM automation

    Requires scope `automations:write`.

  • delete/api/v1/automations/comment-to-dm/{id}

    Delete a comment-to-DM automation

    Requires scope `automations:write`. Cascades to its trigger logs.

  • get/api/v1/automations/comment-to-dm/{id}/logs

    List an automation's trigger logs

    Any authenticated API key (read-scope enforcement not yet applied to this endpoint).

AdAccounts

5 endpoints

Per-network connected ad accounts (Meta, Google, TikTok, LinkedIn, Pinterest, X).

  • get/api/v1/ad-accounts

    List ad accounts

    Requires scope `ad-accounts:read`.

  • post/api/v1/ad-accounts

    Connect an ad account

    Requires scope `ad-accounts:write`. `credentials` is validated live via the network adapter's `connectAdAccount()` when that network is configured server-side (`<NETWORK>_ADS_*` env vars present); otherwise it is stored as given. Always AES-256-GCM encrypted at rest and never returned.

  • get/api/v1/ad-accounts/{id}

    Get an ad account

    Requires scope `ad-accounts:read`.

  • patch/api/v1/ad-accounts/{id}

    Update an ad account

    Requires scope `ad-accounts:write`.

  • delete/api/v1/ad-accounts/{id}

    Disconnect an ad account

    Requires scope `ad-accounts:write`. Sets status=disconnected; cascades to its campaigns, ads, audiences, and tracking tags.

AdCampaigns

6 endpoints

Ad campaigns: objective, budget, and pause/resume state.

  • get/api/v1/ad-campaigns

    List ad campaigns

    Requires scope `ad-campaigns:read`.

  • post/api/v1/ad-campaigns

    Create an ad campaign

    Requires scope `ad-campaigns:write`. `adAccountId` must belong to the caller's tenant. Created in status=draft.

  • get/api/v1/ad-campaigns/{id}

    Get an ad campaign

    Requires scope `ad-campaigns:read`.

  • patch/api/v1/ad-campaigns/{id}

    Update an ad campaign

    Requires scope `ad-campaigns:write`. Status transitions go through `POST /v1/ad-campaigns/{id}/status`, not this endpoint.

  • delete/api/v1/ad-campaigns/{id}

    Delete an ad campaign

    Requires scope `ad-campaigns:write`. Detaches (does not delete) any ads currently assigned to it.

  • post/api/v1/ad-campaigns/{id}/status

    Pause or resume an ad campaign

    Requires scope `ad-campaigns:write`. Body `{ action: "pause" | "resume" }`. `pause` is only valid from status=active and `resume` only from status=paused; any other current status is a 400. Dispatches to the network adapter (best-effort when configured), sets status accordingly, and emits `ad.status_changed`.

Ads

11 endpoints

Individual ads, including boosted posts, lead forms, targeting search, and conversion forwarding.

  • get/api/v1/ads

    List ads

    Requires scope `ads:read`.

  • post/api/v1/ads

    Create an ad

    Requires scope `ads:write`. `adAccountId` (and `campaignId`, when given) must belong to the caller's tenant, and `campaignId`'s adAccountId must match. Created in status=draft unless `status` is given.

  • get/api/v1/ads/{id}

    Get an ad

    Requires scope `ads:read`.

  • patch/api/v1/ads/{id}

    Update an ad

    Requires scope `ads:write`. Only permitted while the ad's current status is draft or paused. Emits `ad.status_changed` when `status` changes.

  • delete/api/v1/ads/{id}

    Delete an ad

    Requires scope `ads:write`.

  • get/api/v1/ads/{id}/analytics

    Get an ad's daily analytics

    Requires scope `ads:read`. Reads from AdMetric.

  • post/api/v1/ads/boost-post

    Boost an organic post into a paid ad

    Requires scope `ads:write`. `postId` must belong to the caller's tenant (404, not leaked, on mismatch). Creates an `Ad` with `postId` set.

  • post/api/v1/ads/create-lead-form

    Create a lead form

    Requires scope `ads:write`. `adAccountId` must belong to the caller's tenant.

  • post/api/v1/ads/lead-forms/{id}/submissions

    Submit a lead against a lead form

    Requires scope `ads:write`. The lead form `{id}` must belong to the caller's tenant (404, not leaked, on mismatch). `data` is validated against the form's field specs — required fields must be present and unknown keys are rejected. Optional `adId` links the lead to a tenant-owned ad. Creates a `Lead` and emits the `lead.received` webhook.

  • post/api/v1/ads/search-targeting

    Search network targeting suggestions

    Requires scope `ads:write`. `adAccountId` must belong to the caller's tenant. Returns a cached echo of the query when the account's network has no credentials configured, so this endpoint is exercisable without ad creds.

  • post/api/v1/ads/send-conversions

    Send conversion events

    Requires scope `ads:write`. `trackingTagId` must belong to the caller's tenant (404, not leaked, on mismatch). Any `userData.email`/`userData.phone` in an event's payload is SHA-256 hashed before persist and before being forwarded. Persists one `AdConversion` per event and forwards them to the network CAPI via the adapter when configured (`forwarded` reflects the outcome; unconfigured networks persist with `forwarded=false`).

AdAudiences

6 endpoints

Custom/lookalike/saved audiences and hashed-member uploads.

  • get/api/v1/ad-audiences

    List ad audiences

    Requires scope `ad-audiences:read`.

  • post/api/v1/ad-audiences

    Create an ad audience

    Requires scope `ad-audiences:write`. `adAccountId` must belong to the caller's tenant. Created in status=building.

  • get/api/v1/ad-audiences/{id}

    Get an ad audience

    Requires scope `ad-audiences:read`.

  • patch/api/v1/ad-audiences/{id}

    Update an ad audience

    Requires scope `ad-audiences:write`.

  • delete/api/v1/ad-audiences/{id}

    Delete an ad audience

    Requires scope `ad-audiences:write`. Cascades to its members.

  • post/api/v1/ad-audiences/{id}/upload

    Upload audience members

    Requires scope `ad-audiences:write`. `id` must belong to the caller's tenant (404, not leaked, on mismatch). Raw email/phone are SHA-256 hashed immediately; only the hash is ever persisted (`AdAudienceMember.hashedValue`) or handed to the network adapter. `memberCount` is bumped by the number of newly-accepted (previously unseen) hashes.

TrackingTags

7 endpoints

Pixels, Conversions API tags, and gtag tags, plus their recorded events.

  • get/api/v1/tracking-tags

    List tracking tags

    Requires scope `tracking-tags:read`.

  • post/api/v1/tracking-tags

    Create a tracking tag

    Requires scope `tracking-tags:write`. `adAccountId` must belong to the caller's tenant. `credentials`, when given, is AES-256-GCM encrypted at rest and never returned.

  • get/api/v1/tracking-tags/{id}

    Get a tracking tag

    Requires scope `tracking-tags:read`.

  • patch/api/v1/tracking-tags/{id}

    Update a tracking tag

    Requires scope `tracking-tags:write`.

  • delete/api/v1/tracking-tags/{id}

    Delete a tracking tag

    Requires scope `tracking-tags:write`. Cascades to its events and conversions.

  • get/api/v1/tracking-tags/{id}/events

    List a tracking tag's events

    Requires scope `tracking-tags:read`.

  • post/api/v1/tracking-tags/{id}/events

    Record a tracking tag event

    Requires scope `tracking-tags:write`.