Authentication
Every request under /v1 needs an API key, except GET /v1/platforms. Keys belong to your postpeg account and can act on every profile in it, so keep them on your server.
API keys
Create keys in the dashboard. A key is shown once, when you create it; we store only a hash of it. Send it as a bearer token:
Authorization: Bearer pp_live_…A missing, malformed or revoked key gets a 401. Revoke a key from the dashboard the moment it leaks; requests with it stop working immediately.
{
"type": "https://postpeg.com/errors/unauthorized",
"title": "Unauthorized",
"status": 401,
"detail": "Missing API key. Send `Authorization: Bearer pp_live_…`.",
"code": "unauthorized",
"request_id": "8f14e45f-ceea-467a-9575-1f2a5c3e6b0d"
}Live and test keys
Keys start with pp_live_ or pp_test_, followed by 32 hex characters. The prefix records which environment you created the key for, and GET /v1/me reports it. Today both kinds behave the same: a test key publishes for real to the accounts you connect. Use them to keep development and CI credentials apart from production, so you can revoke one without touching the other.
Who am I
GET/v1/me
The calling key, your plan and how many accounts are connected.
curl https://api.postpeg.com/v1/me \
-H "Authorization: Bearer $POSTPEG_KEY"{
"key": {
"id": "key_mfz0a1b2c3d4e5f6g7h8i9j0k1",
"name": "Production",
"environment": "live"
},
"plan": {
"id": "trial",
"name": "Trial",
"account_limit": 3,
"trial_ends_at": "2026-10-01T13:55:02.114Z"
},
"usage": {
"connected_accounts": 2
}
}Rate limits
Limits are counted per minute. Writes count against both the general limit and the write limit.
| What | Limit | Counted per |
|---|---|---|
| Every authenticated request | 120 / min | API key (signed-in user in the dashboard) |
| Writes: publish, schedule, connect, reply, send, cancel, create profile (POST and DELETE) | 30 / min | API key, on top of the general limit |
| Requests without a key: GET /v1/platforms, the OpenAPI document and reference, account-connect pages | 60 / min | Client IP address |
| Failed API-key attempts | 30 / min | Client IP address, then 429 for 60 seconds |
Successful authenticated responses carry a RateLimit-Policy header: 120;w=60, or 30;w=60 on writes. Over a limit you get a 429 with code rate_limited, a Retry-After: 60 header and the same number in retry_after. Wait that many seconds, then retry. When you retry POST /v1/posts, send the same Idempotency-Key so the post can’t go out twice.
{
"type": "https://postpeg.com/errors/rate_limited",
"title": "Rate limited",
"status": 429,
"detail": "Rate limit exceeded: 30 changes (publishing, sending, connecting) per minute. Wait and retry after the number of seconds in Retry-After.",
"code": "rate_limited",
"request_id": "8f14e45f-ceea-467a-9575-1f2a5c3e6b0d",
"retry_after": 60
}These limits guard against runaway loops rather than meter usage, and are applied at the edge, so treat them as approximate. Networks have their own limits too; when one pushes back on analytics, comments or messages you get the same 429 shape with the network’s wait time.
The free AI tools on this site have their own limit: 10 requests a minute per visitor, plus a daily cap.
Trial and access
A new account gets a 7-day trial with up to 3 connected accounts and every feature. No card is needed to start. When the trial ends without a plan, every endpoint answers 402 except GET /v1/me and the billing endpoints, so a client can always show how to pay.
{
"type": "https://postpeg.com/errors/subscription_required",
"title": "Subscription required",
"status": 402,
"detail": "Your 7-day trial has ended. Choose a plan (POST /v1/billing/checkout) to keep using the API; your connected accounts are kept for 3 days.",
"code": "subscription_required",
"request_id": "8f14e45f-ceea-467a-9575-1f2a5c3e6b0d"
}