DocumentationPlans and limits

Plans and limits

v1

Monthly allowances for each plan, how usage is counted, and how to read usage and handle limit errors without retry loops.

Limits never create charges. When an allowance is used up, new work is rejected with a clear error until the period resets or you upgrade.

Plans

Every plan includes every feature; plans differ only in allowances. Prices are per month in US dollars, plus applicable tax. Compare plans.

Live allowanceFreeStarterGrowthScale
Price per month$0$9$19$39
Connected live accounts21040100
Successful publications / month203001,5005,000
New media ingested / month1 GB30 GB150 GB500 GB
API requests / month2,00025,000100,000250,000
Comment reads and replies / month (within API requests)2003,00015,00050,000
API requests / minute3060120300
Concurrent media ingests12510
New account connections / month42080200

Test mode

Test keys have their own allowance on every plan: 10 test accounts, 1,000 simulated publications and 10,000 requests a month. Test usage never counts against live allowances, and test accounts never use a live account slot.

How usage is counted

AllowanceWhat counts
Connected accountsLive accounts connected right now. Each TikTok account, Instagram professional account, Facebook Page or YouTube channel uses one slot. Reauthorizing a connected account is free, and disconnecting frees its slot.
New connectionsEach live account that goes from disconnected to connected. This stops accounts being rotated through one plan: Free 4, Starter 20, Growth 80, Scale 200 a month.
PublicationsOne per successful destination, so a post to four accounts can use four. Each destination reserves one unit when the post is accepted, in the period it is scheduled for. The unit is consumed when that destination publishes, in the period it completes, and released if it fails or is canceled. Uncertain deliveries stay reserved until they are reconciled. Idempotent replays are free.
API requestsEvery request made with an API key, including reads and GET /usage. Failed authentication, missing scopes, rate or allowance rejections and server errors (5xx) never count. Dashboard activity never counts.
Comment requestsLive comment reads and replies. They also count as API requests.
MediaBytes Castrook fetches from your media URL to deliver a destination (TikTok and YouTube today). The allowance is checked before any byte moves, and each destination is charged once, for its largest transfer, so retries never add more. The last transfer in a period can go over by at most one file (128 MiB).
RateAPI-key requests per minute, shared by the keys of a workspace and mode: Free 30, Starter 60, Growth 120, Scale 300. Dashboard sessions have a separate limit of 120 a minute.
Concurrent ingestsMedia ingests Castrook runs at the same time for your workspace.

Usage periods

Paid plans reset every month from the moment the subscription started (UTC). Free, beta, complimentary and test-mode allowances reset at the start of each calendar month (UTC). Unused allowance doesn’t roll over. Every meter reports its reset_at.

Read your usage

Any active key can call GET /usage; no scope is needed. It reports the key’s own mode, test or live, and counts as one API request.

curl https://castrook.com/api/v1/usage \
  -H "Authorization: Bearer $CASTROOK_API_KEY"
A live Starter workspace
{
  "data": {
    "mode": "live",
    "plan": "starter",
    "plan_source": "subscription",
    "catalog_version": "2026-09",
    "period": {
      "start": "2026-10-03T14:20:00.000Z",
      "end": "2026-11-03T14:20:00.000Z"
    },
    "reset_at": "2026-11-03T14:20:00.000Z",
    "grace_ends_at": null,
    "accounts": { "used": 6, "limit": 10, "remaining": 4 },
    "publications": {
      "used": 128,
      "reserved": 12,
      "limit": 300,
      "remaining": 160,
      "reset_at": "2026-11-03T14:20:00.000Z"
    },
    "api_requests": {
      "used": 4210,
      "reserved": 0,
      "limit": 25000,
      "remaining": 20790,
      "reset_at": "2026-11-03T14:20:00.000Z"
    },
    "media_bytes": {
      "used": 5400000000,
      "reserved": 0,
      "limit": 30000000000,
      "remaining": 24600000000,
      "reset_at": "2026-11-03T14:20:00.000Z"
    },
    "comment_requests": {
      "used": 310,
      "reserved": 0,
      "limit": 3000,
      "remaining": 2690,
      "reset_at": "2026-11-03T14:20:00.000Z"
    },
    "new_connections": {
      "used": 2,
      "reserved": 0,
      "limit": 20,
      "remaining": 18,
      "reset_at": "2026-11-03T14:20:00.000Z"
    },
    "rate_limit": { "per_minute": 60 },
    "concurrent_ingests": 2
  }
}
FieldMeaning
modetest or live: the key’s environment
planfree, starter, growth or scale
plan_sourceWhy these limits apply: subscription, comp (complimentary), beta or free
catalog_versionThe plan catalog version, currently 2026-09
periodStart and end of the current usage period
reset_atWhen the allowances reset: the end of the period
grace_ends_atWhen the current source stops applying: beta access, a complimentary plan or a failed-payment grace period. Otherwise null.
accountsused, limit and remaining connected accounts
publicationsPublication meter
api_requestsAPI request meter
media_bytesMedia meter in bytes; null in test mode
comment_requestsComment request meter; null in test mode
new_connectionsNew connection meter; null in test mode
rate_limit.per_minuteAPI-key requests allowed per minute
concurrent_ingestsMedia ingests that can run at the same time

Each meter has used (consumed this period), reserved (held for accepted work that hasn’t finished), limit, remaining (the limit minus used and reserved, never below zero) and reset_at.

Rate limits

Every API response includes the rate-limit headers for the key’s workspace and mode, or for your dashboard session.

HeaderMeaning
X-RateLimit-LimitRequests allowed per minute
X-RateLimit-RemainingRequests left in the current minute
X-RateLimit-ResetWhen the current minute ends, in Unix seconds
Retry-AfterOn 429 responses, the seconds to wait. For usage_limit_exceeded it is the time until the allowance resets.

Limit errors

A limit error means nothing was accepted and nothing was charged. Handle it once; never retry it in a loop.

CodeHTTPReturned whenDetails
usage_limit_exceeded429A monthly allowance would be exceeded: API requests, publications, new connections, or media before a transfer. Also reported as a destination error at delivery.metric, mode, plan, limit, used, reserved, remaining, reset_at, upgrade_url, retry_after_seconds
rate_limit_exceeded429The per-minute rate was reachedretry_after_seconds, limit
account_limit_reached409Connecting one more account would exceed the plan, or more than 10 test accountsmode, plan, limit, connected, upgrade_url
account_capacity_exceeded409A live post while more accounts are connected than the plan allows, for example after a downgrade or when beta access ends. Also reported as a destination error at delivery.mode, plan, limit, connected, upgrade_url
HTTP 429 · Retry-After: 432000
{
  "error": {
    "code": "usage_limit_exceeded",
    "message": "This workspace has used its 300 live publications for this period. It resets at 2026-11-03T14:20:00.000Z. Upgrade the plan for a larger allowance.",
    "details": {
      "metric": "publications",
      "mode": "live",
      "plan": "starter",
      "limit": 300,
      "used": 296,
      "reserved": 4,
      "remaining": 0,
      "reset_at": "2026-11-03T14:20:00.000Z",
      "upgrade_url": "https://castrook.com/dashboard/billing",
      "retry_after_seconds": 432000
    }
  },
  "request_id": "req_example"
}

Don’t retry usage_limit_exceeded before reset_at. For a larger allowance, upgrade from Billing in the dashboard; upgrade_url links there. The TypeScript SDK never retries these errors.

TypeScript
try {
  await castrook.posts.create(payload, { idempotencyKey: 'campaign-42-post-7' });
} catch (error) {
  if (error instanceof CastrookError && error.isUsageLimit()) {
    // Nothing was accepted or charged. Try again after the reset.
    console.warn(error.details.metric, 'resets at', error.details.reset_at);
  } else {
    throw error;
  }
}

What keeps working at a limit

  • Work that was already accepted keeps its reservation and is delivered.
  • When the publication, media or new-connection allowance is used up, other requests keep working, including status reads, cancellations and disconnects.
  • When the API request allowance is used up, API keys are rejected until the reset. The dashboard keeps working, because dashboard activity never counts.
  • Billing is always available, so you can upgrade at once.

Plan changes and capacity

Upgrades apply immediately. Downgrades take effect at the next renewal. If a downgrade, a cancellation or the end of beta access leaves more connected accounts than the plan allows, nothing is disconnected or deleted: new live posts fail with account_capacity_exceeded until you disconnect accounts or upgrade. Scheduled posts are checked again before delivery, and a destination that is over capacity or out of allowance fails with the matching error and releases its reservation.