Reference
REST API
Create, schedule and publish posts, upload media and read results from your own code. The API follows the same rules and validation as SPREVA itself.
Your first request
- 1
Create an API key in SPREVA under Developer, then API keys. A Read only key is enough for this example; publishing needs a key with Publishing access.
- 2
List your social accounts:
Terminal curl https://dev-app.spreva.ai/api/v1/social-accounts \ -H "Authorization: Bearer spreva_sk_..." - 3
Read the answer. Results come inside
data, and an account'sidis what you pass asconnectionIdwhen you create a post for it. The sample is shortened: the real object has more fields.JSON { "data": [ { "id": "e81b3f52-0000-4000-8000-000000000005", "provider": "instagram", "displayName": "Acme Studio", "username": "acme", "status": "ACTIVE", "needsReconnect": false } ] }
Basics
Every endpoint is under this address. Send JSON, with the key as Authorization: Bearer followed by the key.
https://dev-app.spreva.ai/api/v1- A key belongs to one workspace and only ever sees that workspace.
- Limit: 120 requests a minute for each person in a workspace, shared by all the keys they created. Past that, the answer is a
429whose message says how many seconds to wait. - Errors come back in the language of the request's
Accept-Languageheader; theircodenever changes. - From a browser signed in to SPREVA, send
x-workspace-idwith the workspace's id instead of a key.
Keys and permissions
A key acts for the person who created it and can never do more than that person's role allows. Owners and admins create keys, on a plan that includes API access, and the full key is shown only once. Each key has the permissions it was given:
posts:read- See posts, their status, results and queues
media:read- See the media library
accounts:read- See the connected social accounts
analytics:read- See analytics
posts:write- Create, edit, schedule, publish and delete posts, and manage queues
media:write- Upload, rename and delete media
webhooks:write- See and add webhook endpoints
ai:write- Use AI. Captions and hashtags also need posts:write; alt text and images also need media:write
Read only gives the four read permissions. Publishing adds posts:write, media:write and ai:write, enough for an automation or an AI agent. A 403 means the key lacks the permission, or its creator's role no longer allows it.
Errors
Every error has the same shape. Branch on code, show message.
{
"error": {
"code": "FORBIDDEN",
"message": "API key needs the posts:write scope for posts:create"
}
}- 400
INVALID_REQUEST · INVALID_JSON · WORKSPACE_REQUIREDThe body or query does not match the endpoint. details lists each field that is wrong. A browser call without x-workspace-id gets WORKSPACE_REQUIRED.
- 401
UNAUTHENTICATEDThe key is missing, mistyped, revoked or expired. Send “Authorization: Bearer <key>”.
- 402
ENTITLEMENT_EXCEEDED · AI_LIMIT_REACHEDThe workspace has no plan in force, is out of AI credits, or its plan does not include this. An owner can choose a plan or buy credits under Settings, then Billing.
- 403
FORBIDDENThe key lacks the permission for this request, or your role does not allow it. Create a key with more access.
- 404
NOT_FOUNDNo such object in this workspace. A key only ever sees the workspace it was created in.
- 409
CONCURRENT_MODIFICATION · INVALID_STATE_TRANSITION · CONFLICT · AI_NOT_CONFIGUREDThe post changed since you read it, it is in a state that does not allow this (publishing a published post), a file you are deleting is still used by a post, or AI is not set up on this installation. Fetch it again and retry.
- 422
VALIDATION_FAILED · PROVIDER_VALIDATION_FAILED · AI_REFUSEDThe content does not fit the account it is going to, or an AI request was declined. GET /providers lists the rules of each network.
- 429
RATE_LIMITED · AI_BUSYMore than 120 requests in a minute from you in this workspace, or too many AI requests at once. For RATE_LIMITED the message says how many seconds to wait; for AI_BUSY, wait a moment.
- 500
INTERNALSomething failed while handling the request, in SPREVA or at a social network. Retry shortly.
- 503
AI_UNAVAILABLEThe AI provider is unavailable right now. Retry shortly.
Endpoints
Paths are relative to the base URL. The OpenAPI document describes every body and parameter, and you can generate a client from it:
https://dev-app.spreva.ai/api/openapi.jsonSocial accounts and networks
get /social-accountsThe connected social accounts.get /providersEach network's rules: formats, placements and limits.
Posts
get /postsPosts, filtered by status, dates, account, network or campaign.post /postsCreate a draft post for one or more accounts.get /posts/{id}A post with its accounts, validation and media.patch /posts/{id}Change a post. Send theversionyou read; if it changed since, the answer is409.delete /posts/{id}Delete a post.post /posts/{id}/publishPublish now. The answer is202: follow the post, or a webhook, for the result.post /posts/{id}/scheduleSchedule it at a time, with a timezone.post /posts/{id}/queueAdd it to a queue's next free slot.post /posts/{id}/retryRetry an account that failed.
Media
get /mediaThe library, with search and filters.post /media/uploadsStart an upload: the answer says where to send the file.post /media/uploads/{id}/completeFinish an upload. The file is then checked and processed.get /media/{id}A file, with its status and what is known about it.delete /media/{id}Delete a file. A file still used by a post answers409.put /media/{id}/alt-textSave or clear a file's alt text.post /media/{id}/alt-text/suggestionSuggest alt text with AI, without saving it.
Analytics
get /analyticsResults for a period.get /analytics/exportThe same results as a CSV file.
Queues
get /queuesThe posting queues.post /queuesCreate a queue with its weekly slots.patch /queues/{id}Change a queue.delete /queues/{id}Delete a queue.
Webhooks
get /webhooksThe webhook endpoints.post /webhooksAdd an endpoint. The answer carries its secret, this once.
AI
get /aiWhether AI is available, the credits left and what each action costs.post /ai/captionsSuggest caption rewrites, translations or hashtags, without saving them.post /ai/imagesGenerate an image. AskGET /media/{id}until it is ready.