Connect, import, and publish
Use connected accounts, transfer media, publish renders, and manage saved research.
Connect accounts in the Sovran dashboard before you use them through the API. The API uses those connections and their existing consent rules. Read GET /integrations for current capabilities before you submit new work. All routes below use the /api/v1 prefix.
Cloud connections belong to the person who created them. The API key must use that person's connection. Read and Write permissions are required for cloud transfers. Publishing requires Read and Publish. New jobs need an active paid plan and an Idempotency-Key.
Read accounts and capabilities
| Task | Method and route |
|---|---|
| Check supported work | GET /integrations |
| List connections | GET /integrations/{provider}/connections |
| List supported provider accounts | GET /integrations/{provider}/accounts |
Provider values are meta, tiktok, google_drive, and dropbox. Connection reads do not return tokens. Meta and TikTok capabilities depend on the current provider controls.
Import or export selected files
| Task | Method and route |
|---|---|
| Import selected files | POST /cloud-drive/{provider}/imports |
| Export stored renders | POST /cloud-drive/{provider}/exports |
| Read transfer status | GET /cloud-drive/{provider}/{imports,exports}/{jobId} |
| Retry eligible failed work | POST /cloud-drive/{provider}/{imports,exports}/{jobId}/retry |
For these routes, use google_drive or dropbox as the provider. Imports accept 1–20 file IDs from the connected account. Exports accept 1–20 stored render job IDs and a saved destination ID. See transfer limits and recovery.
Import one selected file:
{
"projectId": "<PROJECT_UUID>",
"files": [{ "id": "<CONNECTED_ACCOUNT_FILE_ID>" }]
}Export one stored render:
{
"projectId": "<PROJECT_UUID>",
"renderJobIds": ["<STORED_RENDER_JOB_UUID>"],
"destinationId": "<SAVED_DESTINATION_UUID>"
}The response is 202 with a public job ID. Read the returned status URL or GET /jobs/{jobId}. Send {} to the retry route with a new Idempotency-Key only when the failed work permits a retry. An unknown remote upload needs review before another submission.
Import one Dropbox folder page
Use POST /cloud-drive/dropbox/syncs with projectId, folderId, optional maxFiles (1–20), and optional cursor. This imports at most 20 selected files from one page. It does not save a recurring folder.
Read it with GET /cloud-drive/dropbox/syncs/{jobId}. Stop it with POST /cloud-drive/dropbox/syncs/{jobId}/stop and {}. Stop remains available after plan expiry.
Google Drive folder sync is discontinued. Its /cloud-drive/google_drive/syncs routes return 410. Use selected-file imports.
Saved Dropbox folders
A saved folder imports new changes. It does not import existing files when you create it. Use an explicit scan when you need existing files.
Add a folder
Connect Dropbox in the dashboard first. Creation requires Read and Write permissions and an Idempotency-Key.
Send this request body:
{
"projectId": "<PROJECT_UUID>",
"folderId": "<CONNECTED_DROPBOX_FOLDER_ID>"
}The response is 201. The saved folder belongs to the key creator and one workspace. It uses that creator's dashboard connection. New changes are polled every five minutes while the folder is active and processing is enabled. Each new poll checks the key, membership, role, permissions, and paid plan. Accepted import batches can finish after key revocation.
| Task | Method and route |
|---|---|
| List saved folders | GET /cloud-drive/dropbox/folder-syncs |
| Read one folder and its current revision | GET /cloud-drive/dropbox/folder-syncs/{syncId} |
| Read saved file states | GET /cloud-drive/dropbox/folder-syncs/{syncId}/files |
These reads do not download media. Manage saved API folders through the customer API. They do not appear in the dashboard's native folder controls. Native dashboard folders cannot be changed through this API.
Pause, resume, or disconnect
Read the current updatedAt before a change. All changes require an Idempotency-Key. A changed revision returns 409.
Pause the folder:
{
"status": "paused",
"expectedUpdatedAt": "<FOLDER_UPDATED_AT>"
}Use status: "active" to resume. Pause and resume require Read and Write. Disconnect requires Read and Delete.
Disconnect the folder:
{ "expectedUpdatedAt": "<FOLDER_UPDATED_AT>" }Pause and disconnect remain available after plan expiry. Creation, activation, new polls, and explicit runs require a paid plan. After active folder jobs finish, the same creator can repeat the original create request to reconnect a disconnected folder. The folder retains its history and starts a new cursor from the current state.
Run a poll or scan
Scan one page:
{
"mode": "scan",
"expectedUpdatedAt": "<FOLDER_UPDATED_AT>"
}Use mode: "changes" for a changes poll. The response is 202 with a job ID. Read GET /jobs/{jobId}. The job's children list gives each import job's ID, status, counts, and safe errors. Its outputs list gives itemId, assetId, and mediaAvailable.
When scanHasMore is true, read the current folder revision and submit another explicit scan after the current scan completes. The final scan establishes the cursor for later changes. A partial scan preserves the previous changes cursor. The API does not start a historical scan automatically.
If the cursor fails with sync_cursor_reset, read the folder revision and request an explicit scan. If automatic polling stops with sync_claim_limit, read the folder and submit an explicit run to continue its saved page. See folder size and daily limits.
A failed metadata job with sync_provider_unavailable can be retried with POST /jobs/{jobId}/retry, {}, and a new Idempotency-Key. Other folder failures return retry_not_allowed. Accepted media import children have their own retry routes. Read child results before you retry them.
Missing stored output changes a successful job to requires_action. A job does not report available media from a provider success flag alone.
Publish a render or launch ads
| Task | Submit | Read status |
|---|---|---|
| Publish a video | POST /publications/{provider} | GET /publications/{provider}/{jobId} |
| Launch ads | POST /ad-launches/{provider} | GET /ad-launches/{provider}/{jobId} |
Use meta or tiktok as the provider. Read GET /integrations first. Use stored render references. Media must be a stored 9:16 MP4 with saved duration, FPS, resolution, size, and MIME metadata. A legacy output without this metadata returns 409 media_metadata_required. Create a new render when needed.
Publish a stored render to Facebook:
{
"project_id": "<PROJECT_UUID>",
"render_job_id": "<STORED_RENDER_JOB_UUID>",
"page_id": "<CONNECTED_META_PAGE_ID>",
"destinations": ["facebook"],
"facebook_caption": "See our latest offer."
}TikTok requires its supported consent fields and native posting controls. The OpenAPI schema lists the required fields for each provider and publication type.
For eligible failed work, send {} with a new Idempotency-Key to POST /publications/{provider}/{jobId}/retry or POST /ad-launches/{provider}/{jobId}/retry. The retry needs the same permissions.
Meta ad launches accept one render and have one provider submission attempt. Their retry route returns 409 manual_review_required. Check Meta Ads Manager before you submit a new ad request. An unknown provider result needs review. See publishing limits and recovery.
Find and save research
Research searches need Read and Generate permissions, a paid plan, and an Idempotency-Key. Check current capabilities before new work. A search returns one provider page. It does not follow a cursor or download source videos.
Facebook companies and ads
Find companies:
{ "kind": "companies", "query": "Company name" }Use a returned pageId to request ads through the same route.
Find ads for a company:
{
"kind": "ads",
"pageId": "<RETURNED_PAGE_ID>",
"companyName": "Company name",
"country": "US",
"status": "ACTIVE",
"sortBy": "total_impressions"
}Ads accept country (ALL or a two-letter country), status (ALL, ACTIVE, or INACTIVE), language, startDate, endDate, and cursor. Dates use YYYY-MM-DD. sortBy accepts total_impressions or relevancy_monthly_grouped. If the response includes nextCursor, send it in a separate request with a new Idempotency-Key.
TikTok videos and trends
Request hashtag suggestions and videos:
{
"query": "productivity",
"country": "US",
"dateRange": "7DAY",
"category": "ALL"
}An empty query requests trends. The response includes applied filters and data age. TikTok returns at most 20 videos. The OpenAPI schema lists supported country, dateRange, and category values. Use hashtagId to select a returned hashtag.
Save and manage results
Saving needs Read and Write. Use a completed query from the same project.
Save one result:
{
"queryJobId": "<COMPLETED_QUERY_JOB_UUID>",
"collection": "ads",
"resultId": "<RETURNED_RESULT_ID>",
"note": "Review the opening hook."
}Facebook collections are ads, companies, and views. TikTok collections are videos, hashtags, and views. Use a result ID except for views. A view saves the query filters. Sovran copies source references from the saved query. The request does not accept source URLs or preparation fields.
| Task | Method and route | Input |
|---|---|---|
| List saved items | GET /projects/{projectId}/research/{provider}/saves/{collection} | None. |
| Read one item | GET /projects/{projectId}/research/{provider}/saves/{collection}/{savedId} | None. |
| Update an ad or video note | PATCH /projects/{projectId}/research/{provider}/saves/{collection}/{savedId} | note and expectedUpdatedAt. |
| Delete one item | DELETE /projects/{projectId}/research/{provider}/saves/{collection}/{savedId} | expectedUpdatedAt; Delete permission. |
A revision conflict returns 409. Active source work must finish or be resolved before deletion.
Transcribe or adapt saved research
Use a saved Facebook ad or TikTok video ID. Both tasks need Read and Generate, a paid plan, and an Idempotency-Key. The source details and preparation paths remain server-owned.
Send this request body:
{ "expectedUpdatedAt": "<SAVED_ITEM_UPDATED_AT>" }This returns a job when research transcription is available. It accepts one source of at most 25 MiB (26,214,400 bytes) and five minutes. A retry uses saved audio and completed provider results. An unknown provider result needs review.
Request five hooks:
{
"mode": "hooks",
"expectedUpdatedAt": "<SAVED_ITEM_UPDATED_AT>"
}Use mode: "script" for one script. A script requires a saved transcript. Both modes need active project context. The job saves the accepted source text and context before generation. It does not download media.
Read saved and saveStatus in the result. If the saved item changed during generation, the output remains available with saveStatus: "revision_conflict" for review.
Refresh Meta insights
Connect Meta and link one ad account to the project in Sovran.
Send this request body:
{}Use Read and Write permissions and an Idempotency-Key. The job refreshes metadata for one account and one project. It reads at most 25 ads or the lower current capability limit. It does not download videos or run media enrichment.
A cooldown returns 429 insights_cooldown with Retry-After. Wait for that interval. A job can report partial results if some metadata writes fail. Read its completed count and safe error count. Read current saved data with GET /projects/{projectId}/insights, /insights/ads, or /insights/hooks.
Manage rules, team, and project settings
| Task | Routes | Guard |
|---|---|---|
| Manage dictionary rules | /dictionary | Saved revisions apply to rule changes. |
| Apply dictionary rules | POST /dictionary/apply | Supply 1–100 explicit transcriptIds. Protected changes need the creator's current owner or admin role. |
| Read workspace details | GET /workspace | Workspace access. |
| Manage members | /workspace/members | Current role and owner rules. |
| Manage invitations | /workspace/invitations | Creation and resend send an email. Use the target's exact address. |
| Manage project settings | /projects/{projectId}/settings | Saved revision. |
| Manage naming rules | /projects/{projectId}/naming-templates and /naming-fields | Saved revision for updates and deletes. |
Dictionary jobs preserve their accepted rule snapshot. Saved transcript and caption revisions prevent overwriting later edits. They do not download source videos. Member removal first revokes creator-owned cloud access. Workspace rename and owner controls use the dashboard's existing rules.
Read the OpenAPI schema for each resource's supported methods and fields.