Get started

Authenticate every request with your API key in a header. One key works for every endpoint and platform.

Send your API key in the x-api-key header of every request:

Shell
curl -H "x-api-key: $SOCIALTAP_API_KEY" "https://socialtap.dev/v1/tiktok/profile?..."

authorization: Bearer <key> works too (what most HTTP and MCP clients send); when both are sent, x-api-key wins.

Keys and scopes

Get a key on the signup page; AI agents get one for you with auth.md: you approve it in your browser. Keys start with st_live_ and make real requests, paid with your account's credits (new accounts start with 100 free). Each key has scopes (what it may call) and can have a spend limit, an expiry and an IP allowlist; a key that may not make a request gets forbidden (HTTP 403) with the reason. Manage keys in the dashboard or with the API keys routes.

Request headers

HeaderTypeDescription
x-api-keystringYour API key.
authorizationstringBearer <your API key>: the same key as x-api-key, in the form most HTTP and MCP clients send (x-api-key wins when both are sent).
x-account-idstringDashboard session only: the account (acct_…) to act on, one of Session.accounts (default: the person's own); one they aren't on is refused (forbidden, reason not_a_member). API keys ignore it.
x-client-request-idstringYour own ID for the request (1–128 printable ASCII characters): echoed back and logged with ours, so support can find a request whose response never reached you.
traceparentstringW3C Trace Context of your trace: recorded with the request (its trace ID) so a trace can be matched to ours; SocialTap starts its own trace.
idempotency-keystringOn any POST: your unique key for the request (1–255 printable ASCII characters; a UUID is ideal), kept 24 hours. Retrying with the same key and body never repeats the work: the answer is the first request's result, in its current state.
preferstringRFC 7240. respond-async on any endpoint request runs it as a one-request job: the answer is 202 with the job (Location: its URL) instead of the result.
cache-controlstringmax-age=N accepts a cached response up to N seconds old, like the max_age parameter (max_age wins when both are sent). Other directives are ignored.

Response headers

HeaderTypeDescription
x-request-idstringUnique request ID; include it when contacting support.
x-credits-chargedintCredits charged for this request (0 for errors and cache hits).
x-credits-remainingintAccount balance after this request; for a busy account an estimate that may not yet subtract concurrent requests (about a second of usage), never below the real balance.
retry-afterintSeconds to wait before retrying; sent only with the codes whose retry_after is set in the error codes list (never on credit errors).
allowstringMethods the endpoint accepts (method_not_allowed only).
ageintSeconds since the data was fetched (cache hits only).
x-client-request-idstringYour x-client-request-id, echoed (also meta.client_request_id).
ratelimit-policystringThe account's runaway-protection ceiling as an IETF RateLimit-Policy field, as enforced: a token bucket of q requests (twice the ceiling in requests per second, at least 10) that refills in w seconds: "account";q=<requests>;w=<seconds>. Not a plan limit.
ratelimitstringWhat is left of the ceiling (IETF RateLimit field): "account";r=<requests that may be sent at once now>;t=<seconds until the bucket is full again>.
deprecationstringRFC 9745: the endpoint is deprecated, as of this date (@<unix seconds>; may be in the future). Also in meta.warnings.
sunsetstringRFC 8594: when a deprecated endpoint stops answering (HTTP-date); from then on it answers endpoint_retired.
linkstringRFC 8288 links: rel="next" is the next page of a list (while page.has_more), the same request with cursor set; rel="deprecation" is a deprecated endpoint's notice.
locationstringOn 202 answers: the job's URL (GET it, free, for its status).
preference-appliedstringRFC 7240: respond-async when Prefer: respond-async turned the request into a job (202).
idempotent-replayedbooltrue when the answer replays an earlier request with the same Idempotency-Key (it shows the resource's current state).

x-credits-charged and x-credits-remaining are on every response to an authenticated request, successful or not: errors show a charge of 0 and your unchanged balance. A request rejected for its key has neither, because there is no account to report on.

Rotate a key

POST /v1/api_keys/{id}/rotate_secret gives a key a new secret, shown once; its ID, scopes, limits and usage stay. The old secret works for previous_secret_expires_in more seconds (default 1 day, at most 7 days; the key's previous_secret_expires_at), but only for calls that need no admin scope: others answer forbidden, reason previous_secret. Rotating again ends the oldest secret, and revoking ends both, within a minute everywhere. The dashboard's API keys page has a Rotate button.

Rotate when a secret may have been exposed and nothing suggests it was used: send 0 to end the old one now. After a leak, revoke the key instead (DELETE /v1/api_keys/{id}). A rotation keeps the key, its jobs and every key it made; revoking stops its jobs and takes the admin keys below it along, and its answer lists the keys it leaves working (left_standing), which the dashboard offers to revoke too. Then check your webhook endpoints.

If the answer to your own rotation is lost, only a person can recover: the old secret can't manage the key, and replaying the answer to it would hand the new secret to whoever holds the old one. Sign in and rotate the key in the dashboard, or rotate it with another admin key.

Missing or invalid keys

A request without a key, or with an unknown or revoked one, fails with unauthorized (HTTP 401), carries no credit headers and costs nothing.

Rate limits

Plans do not limit request rate: you pay for credits (see Pricing), and you can send requests as fast and as many in parallel as your balance covers.

Each account has a high safety ceiling on requests per second that only stops runaway clients, such as a retry loop without backoff. Above it, requests fail with rate_limited (HTTP 429) and cost nothing; wait the number of seconds in the retry-after header, then retry. If your sustained traffic needs more, ask support and the ceiling is raised for your account. An account that has never paid has a lower ceiling, which its first payment removes within a minute.

Failed requests are free, and they stay free within a limit: if your failures cost far more upstream in an hour than your successful requests paid for, requests answer rate_limited until that passes, and the message says so. Failures alongside a normal share of successes never meet it, and neither do failures that cost nothing to find out.

Your account's ceiling is max_rps in GET /v1/account. To see how close you run to it, GET /v1/usage/rate reports the busiest second (peak_rps), the average rate and the requests refused with rate_limited, per 10 minutes, hour or day, and the dashboard's Usage page charts them against the ceiling.

Last updated