ClientPoster API for developers
Last updated: 17 October 2026
ClientPoster is an AI video and content studio for social media agencies: multi-scene videos of up to 30 minutes, scene-by-scene editing, on-brand post text and images. This API lets you do your agency's ClientPoster work from other systems and AI assistants: manage your clients and their brand guides, generate post text, images, image series, documents and videos for them, correct the scenes of a video, and send the produced content to your client for approval.
Quick start with Claude
If you work with Claude Code or the Claude API, give Claude three things: your API key (the CP_API_KEY environment variable), the plain-text version of this guide prepared for AI tools, and the OpenAPI definition. Then ask in plain language, for example:
For client X, prepare a 60-second, 6-scene horizontal product video for LinkedIn; tell me the price first and generate it only if I approve.
Claude lists your clients, previews the price, starts the generation and polls the job until it is finished; on request it corrects a single scene or sends the content to your client for approval. The calls behind this are described in the sections below.
1. Getting started
Create an API key: sign in to ClientPoster and open the API Keys page in the Account section of the menu. The agency owner or an admin can create keys; API access is available on paid plans. The key is shown only once — keep it like a password.
Base address of all requests: https://api.clientposter.com/api/v1
In the examples the key is read from the CP_API_KEY environment variable (bash or zsh; on Windows use Git Bash or WSL). The first request returns who the key belongs to:
curl -H "Authorization: Bearer $CP_API_KEY" \
"https://api.clientposter.com/api/v1/profil"
2. Authentication and permissions
Send the key as a Bearer token in the Authorization header of every request. The key acts on behalf of the person who created it: if that person is removed from the team or suspended, the key stops working; its rights are the intersection of the permissions chosen at creation and that person's current role.
Each operation requires one permission; the API definition states which one (x-clientposter-permission):
| Permission | Value | What it allows |
|---|---|---|
| Read | read |
Customers, content, credit summary, price quotes, image and video downloads, reports (Agency+) |
| Content generation | generate |
Generating, fixing and editing text, images and video — spends credits |
| Customers and brand guide | customers |
Creating and updating customers, brand voice, keywords, logo |
| Approvals | approvals |
Sending content to the customer for approval by email, tracking it, withdrawing it; emailing content and reports |
3. Errors and rate limit
Errors are returned as RFC 7807 problem details (application/problem+json) with a stable error code (kod) and a trace ID for support (traceId); field validation errors list each field in an errors object. Error text is in Turkish or English according to the Accept-Language header.
- 400 — the request is invalid; see the errors object.
- 401 — the key is missing, unknown, revoked or expired.
- 403 — the operation is not open to API keys, the key lacks the permission, your plan has no API access, or your plan does not include the operation (reports through the API need Agency+).
- 404 — the record was not found or belongs to another agency.
- 409 — a generation started with the same request key is still running.
- 429 — rate limit exceeded; wait for the number of seconds in the Retry-After header.
Rate limit: 120 requests per minute per key.
4. Example flow: generate a post and send it for approval
The steps can be run in order. Replace the upper-case placeholders (CLIENT_ID, CONTENT_ID, MEDIA_ID) with the IDs from the previous step's response.
Find your client
Lists your clients and their IDs (id).
curl -H "Authorization: Bearer $CP_API_KEY" \
"https://api.clientposter.com/api/v1/musteriler"
Add a client if needed
Creates a new client (customers permission); language (dil) and tone (ton) must be one of the values in section 5.
curl -X POST -H "Authorization: Bearer $CP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"ad": "Example Cafe",
"sektor": "Cafe and restaurant",
"dil": "en",
"ton": "friendly"
}' \
"https://api.clientposter.com/api/v1/musteriler"
See your credit balance and prices
Returns your clients, your credit balance and the credit price of each content type in one response; spends no credits.
curl -H "Authorization: Bearer $CP_API_KEY" \
"https://api.clientposter.com/api/v1/icerik/sihirbaz"
Ask the price of one item
The credit price of a content type for a number of platforms (here text, one platform). It is calculated with the same formula as the amount charged at generation and spends no credits.
curl -H "Authorization: Bearer $CP_API_KEY" \
"https://api.clientposter.com/api/v1/icerik/bedel/text/1"
Upload reference images (optional)
To use a product, logo, place or person image when generating images or videos, upload it first (generate permission, spends no credits). The body is multipart/form-data: the request as JSON in the talep part (hakBeyani confirms you have the right to use the images) and each file in its own part named dosyalar. Put each returned image id in the referanslar field of the generation request with its role (product, logo, place, person) and send referansHakBeyani as true.
curl -X POST -H "Authorization: Bearer $CP_API_KEY" \
-F 'talep={"hakBeyani":true};type=application/json' \
-F "dosyalar=@product.jpg" \
"https://api.clientposter.com/api/v1/icerik/referans"
Generate the content
Spends credits (generate permission). The response carries the generated text, its variants and the content ID (icerikId); text and single images are generated within the request.
curl -X POST -H "Authorization: Bearer $CP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"talepAnahtari": "autumn-menu-0001",
"musteriId": "CLIENT_ID",
"amac": "awareness",
"platformlar": [
"linkedin"
],
"tip": "text",
"dil": "en",
"ton": "friendly",
"uzunluk": "short",
"brief": "Announce our new autumn menu with warm drinks and fresh pastries. Invite people to visit this week."
}' \
"https://api.clientposter.com/api/v1/icerik/uret"
Send a unique talepAnahtari for each new generation (for example a UUID). A request repeated with the same key is not charged twice: if the first generation has finished it returns the same result, if it is still running it returns 409.
Follow long-running jobs
Image series and videos are generated in the background. Read the content details every few seconds; when the job has finished, the ready files appear in the medyalar list.
curl -H "Authorization: Bearer $CP_API_KEY" \
"https://api.clientposter.com/api/v1/icerik/CONTENT_ID/detay"
Download the file
Downloads the file by its media ID; the response may redirect to a short-lived signed address (-L follows it). The old curl bundled with Git Bash on Windows (8.8.0) may fail on that address with error 43; use Windows' own curl or a current curl.
curl -L -o media.bin -H "Authorization: Bearer $CP_API_KEY" \
"https://api.clientposter.com/api/v1/medya/MEDIA_ID/icerik"
Send it to your client for approval
Your client receives an approval link by email (approvals permission); the client decides only on the page behind that link. Validity 1–30 days.
curl -X POST -H "Authorization: Bearer $CP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"icerikId": "CONTENT_ID",
"aliciEposta": "client@example.com",
"aliciAd": "Alex Morgan",
"ajansNotu": "Please review the post for this week.",
"gecerlilikGun": 7
}' \
"https://api.clientposter.com/api/v1/onay/talep"
Follow the approval status
Returns the status of the approval request and the client's decision.
curl -H "Authorization: Bearer $CP_API_KEY" \
"https://api.clientposter.com/api/v1/onay/ozet/CONTENT_ID"
Read the report (Agency+)
The period report: published posts, content produced, approvals and credits spent, with the previous period of the same length; daily series, clients, platforms and the period's posts. gun is 7, 30 or 60 (default 30, days up to today, Turkey time); musteri=CLIENT_ID gives that client's report. Reports through the API are on the Agency+ plan; other plans get 403.
curl -H "Authorization: Bearer $CP_API_KEY" \
"https://api.clientposter.com/api/v1/raporlar?gun=30"
Download the report as PDF
The same query as an A4 PDF (under your agency's name, white-labelled); /raporlar/csv returns the same report as CSV. POST /raporlar/eposta (approvals permission) emails the PDF; its body is gun, musteriId, adres and optional adSoyad and not. PDF and email are limited per user per hour.
curl -L -o report.pdf -H "Authorization: Bearer $CP_API_KEY" \
"https://api.clientposter.com/api/v1/raporlar/pdf?gun=30&musteri=CLIENT_ID"
5. Valid field values
These fields are not free text; they accept only the values below. The list is the very set the product validates and it is also written as an enum in the API definition. The chosen content type must be supported on every chosen platform.
amac
| Value | Meaning |
|---|---|
awareness |
Awareness |
engagement |
Engagement |
traffic |
Traffic |
lead |
Lead generation |
sales |
Sales |
hiring |
Hiring |
platformlar
| Value | Meaning |
|---|---|
linkedin |
|
instagram |
|
facebook |
|
tiktok |
TikTok |
youtube |
YouTube |
tip
| Value | Meaning |
|---|---|
text |
Text only |
image |
Single image |
multi_image |
Multi image |
carousel |
Carousel |
document |
Document |
short_video |
Short video |
long_video |
Long video |
story |
Story |
poll |
Poll |
link |
Link share |
dil
| Value | Meaning |
|---|---|
tr |
Turkish |
en |
English |
de |
German |
fr |
French |
es |
Spanish |
ar |
Arabic |
ru |
Russian |
nl |
Dutch |
it |
Italian |
ton
| Value | Meaning |
|---|---|
professional |
Professional |
friendly |
Friendly |
witty |
Witty |
inspiring |
Inspiring |
educational |
Educational |
authoritative |
Authoritative |
uzunluk
| Value | Meaning |
|---|---|
short |
Short |
medium |
Medium |
long |
Long |
videoCozunurlugu
| Value | Meaning |
|---|---|
720p |
720p (HD) |
1080p |
1080p (Full HD) |
4k |
4K (short video only) |
gorselCozunurlugu
| Value | Meaning |
|---|---|
512 |
512 class |
1k |
1K class |
2k |
2K class |
4k |
4K class |
kullanimYerleri
| Value | Meaning |
|---|---|
social_media |
Social media |
website |
Website |
blog |
Blog |
google_ads |
Google Ads |
meta_ads |
Meta ads |
email |
|
presentation |
Presentation |
ecommerce |
E-commerce |
print |
|
other |
Other |
gorselBosAlan
| Value | Meaning |
|---|---|
left |
Left |
right |
Right |
top |
Top |
bottom |
Bottom |
gorselBicimi
| Value | Meaning |
|---|---|
jpeg |
JPEG |
png |
PNG |
webp |
WebP |
videoBicimi
| Value | Meaning |
|---|---|
vertical |
Vertical 9:16 |
horizontal |
Horizontal 16:9 |
fonMuzigi
| Value | Meaning |
|---|---|
none |
No music |
soft |
Soft background music |
videoLogoKonumu
| Value | Meaning |
|---|---|
top_left |
Top left |
top_right |
Top right |
bottom_left |
Bottom left |
bottom_right |
Bottom right |
top_center |
Top centre |
bottom_center |
Bottom centre |
karakterler[].cinsiyet
| Value | Meaning |
|---|---|
female |
Female |
male |
Male |
karakterler[].yas
| Value | Meaning |
|---|---|
child |
Child |
teen |
Teenager |
adult |
Adult |
middle_aged |
Middle-aged |
senior |
Senior |
6. Technical limits
The numbers are the values the product's validator uses; a request outside a limit is rejected with 400 and the errors object names the field.
| Limit | Field |
|---|---|
| Short video: one scene, 10 seconds. | tip = short_video |
| Long video: 20–1800 seconds in 10-second steps (2–180 scenes; each scene 10 s). The actual cap is your plan's scene limit. | tip = long_video · videoSuresi |
| Maximum video scenes per plan: Free 180 · Başlangıç 180 · Ajans 180 · Ajans+ 180. | - |
| Video resolution: 720p · 1080p · 4k. Long videos: 720p · 1080p only. | videoCozunurlugu |
| Video aspect ratio: vertical 9:16 (vertical) or horizontal 16:9 (horizontal). | videoBicimi |
| Scene description: 5–3000 characters. | sahneler[].tarif |
| Characters: at most 5 per video; at most 3 visible and 2 speaking characters per scene. | karakterler · sahneler[].karakterler |
| Reference images: at most 4 in the person role; at most 10 product, logo and place images for a single image and 3 for a video; total size at most 10 MB. | referanslar |
| Long videos are generated scene by scene in the background (at most 3 scenes at once per job) and then assembled; follow progress through the content details. | - |
| Image size: any width × height, 256–6000 pixels per side. The image is generated in the closest of these provider aspect ratios, centre-cropped and scaled to the exact pixels: 8:1 · 4:1 · 21:9 · 16:9 · 3:2 · 4:3 · 5:4 · 1:1 · 4:5 · 3:4 · 2:3 · 9:16 · 1:4 · 1:8. The resolution class must cover the target (at most 20% upscaling). | gorselGenislik · gorselYukseklik |
| Image resolution class: 512 · 1k · 2k · 4k. | gorselCozunurlugu |
| Image file format: jpeg · png · webp. | gorselBicimi |
| Multi-image and image series: 2–10 images; an image list with separate prompts up to 50 images. | gorselAdedi · gorselListesi |
| Document (PDF): 3–10 pages. | dokumanSayfaSayisi |
| Poll: 2–4 options; duration 1 · 3 · 7 · 14 days. | anketSecenekSayisi · anketSureGun |
| Text fields: brief 10–4000 characters · extra note up to 1000 · request key up to 80 characters. | brief · ekNot · talepAnahtari |
| Approval link validity: 1–30 days. | gecerlilikGun |
| Content retention (days, per plan): Free 7 · Başlangıç 60 · Ajans 180 · Ajans+ 365. The period is set when the content is created and is given in the saklamaBitis field of content responses; when it ends, image, video and document files are deleted and the text remains. On a move to a higher plan, saklamaBitis of existing content extends to the new plan's period, counted from its creation date; it does not shorten on a downgrade. | - |
7. Video scenes
In a long video every scene is generated as a separate clip and the AI does not see the other scenes' prompts, so the shared information is written again in every scene's prompt. A scene's prompt is assembled in this order:
- Header: which scene of the video this is, a continuity sentence, the clip length and a single shot.
- Brand information from the client's brand guide: brand name, sector, target audience, production notes and what must not appear in the video (banned words).
- The reference images sent to this scene, in order and with their roles (product, logo, location, character).
- The characters visible in the scene: age and gender, looks, personality and voice; word for word the same in every scene so that face and voice stay the same across clips.
- The scene's location, if one is selected: its description and photo.
- SAHNE: followed by the request's brief (overall description). When filled it is written in every scene; in a long video it may be empty if every scene has its own description.
- BU SAHNE: followed by the scene's description (sahneler[].tarif); if it is empty, a moment that fits the overall description is asked for.
- DEGISENLER: the changes written from the start of the video up to this scene, with scene numbers and in order.
- KADRAJ: only when the overlay image is placed right or left; that half of the frame stays empty and the person stands in the other half pointing at the image.
- EK NOT: the request's ekNot field (in every scene).
- Audio: the lines with the speaker's name, in the order they are spoken; with no lines the prompt says explicitly that no one speaks.
- At the end: background music, a physics rule and the general rules: no readable text, logos or watermarks; no recognizable real faces other than those in the references.
If the prompt exceeds 16000 characters it is shortened in this order: production notes, target audience, the oldest changes, brief. The scene description, the lines, character and location information, the extra note and the rules are never cut.
Scene fields
| Field | Meaning |
|---|---|
sahneler[].tarif |
What happens in this scene (5–3000 characters); if empty, a moment that fits the overall description. |
sahneler[].karakterler |
Characters visible in this scene: their numbers in the karakterler list, starting at 1 (at most 3). A voice-only character cannot be listed here. |
sahneler[].sozler |
Spoken lines in order: karakter (number, starting at 1), soz and an optional nasil (delivery note, at most 60 characters). At most 4 lines and at most 2 speakers including the narrator per scene; the lines must fit the 10-second clip. An on-screen speaker must be in this scene's karakterler list; a voice-only narrator speaks without being listed. |
sahneler[].mekan |
This scene's location: its number in the mekanlar list, starting at 1. The location's description and photo (a place reference whose mekan field points to it) go into this scene's prompt verbatim; if empty, the scene description tells where it happens. |
sahneler[].referanslar |
Media IDs of the product and logo images to use in this scene (from the request's referanslar list). It selects, it does not add: an image selected for a scene goes only to the scenes that select it; an image selected for no scene goes to every scene. |
sahneler[].degisen |
What changes from this scene on (at most 200 characters; e.g. clothing, weather, time of day). Not allowed in the first scene; carried into later scenes and accumulated, a later change overrides an earlier one. |
sahneler[].tamEkranGorsel |
An image overlaid on this scene during editing (role fullscreen in the request's referanslar list). It is not sent to the AI and is not the first frame: it appears 1 s after the speech starts and disappears 0.5 s before it ends; without speech it shows during 30–80% of the clip. Long videos only, at most 8 per video; not charged and not counted toward the reference limit. |
sahneler[].tamEkranYerlesimi |
Where the overlay image goes: full · right · left (default full). Side placement only in horizontal (16:9) video; then the prompt asks to keep that half of the frame empty and the person to point at the image. |
Images and limits
The request's referanslar list may hold at most 3 product or logo images for the whole video; scene-level referanslar do not add to this number. Character images (one per character, at most 5 characters), location photos (one per location) and fullscreen images do not count toward it. At most 5 images go to the AI in one scene: the images of the characters visible in it, the location photo and that scene's product and logo images. Images are sent for consistency, not placed as the first frame; setting a scene's first frame directly is not supported.
Characters and narrator
Characters are defined in the request's karakterler list; numbers start at 1 (the first character is 1), and so do locations. For a narrator who is only heard, set yalnizSes to true: never on screen, no image, cannot be listed in a scene's karakterler, but speaks in sozler. sozleriAiYazsin true lets the AI write the narrator's lines scene by scene (voice-only characters only, at most one per video; no manual lines for that character). A person image is bound to a character: role person and the karakter field in referanslar (one image per character). How proper names in the speech are pronounced comes from the pronunciation hints in the client's brand guide (one per line, written form: pronunciation, e.g. ClientPoster: Klaynt Poster; okunusIpuclari in the wizard endpoint); for one video send markaSecimi.okunusMetni. Before a video with speech, check the client's hint and ask about the brand name if it is empty. In Turkish content the pronunciation replaces the written form in the speech sent to the video model; the saved lines, subtitles and post text keep the written form. In other languages it goes into the prompt as a separate line.
Video signature and discount
If the generation request sends videoImzasi true, the ClientPoster signature is added to the top-left corner of the video in brand colors and on paid plans the video's credit price is 10% lower; the signature is burned in and cannot be removed later. On the free plan the signature is always added and there is no discount. You can preview the discounted price with imza=true on the price endpoint. The signature text follows the content language (tr, en, de, fr, es, it, nl); other languages get the English text.
8. Editing a video
A delivered video can be edited scene by scene; after every operation that changes the picture the video is assembled again. Paid operations are safe to retry with the talepAnahtari field: a second request with the same key does not spend credits again.
| Operation | Endpoint | Permission | Cost |
|---|---|---|---|
| A scene's raw (untrimmed) clip, to choose the range before trimming. | GET /api/v1/medya/icerik/{icerikId}/sahne/{sira}/klip |
read |
Free |
| Manual trim: body sira, baslangicMs, bitisMs; the part of the raw clip kept in the video (milliseconds from the clip start; at least 1 s, ending by 60 s). Sending baslangicMs and bitisMs empty removes manual trimming and returns to automatic trimming. | POST /api/v1/icerik/{icerikId}/video-sahnesi/kirp |
generate |
Free |
| Trims several scenes in one request: body sahneler (each item is the trim endpoint's body; at most 180 scenes, each once). All are saved together and the video is rebuilt once; if one scene is not ready, none is saved. In the content details, each scene's tutulanBaslangicMs and tutulanBitisMs give the part of the clip the video uses. | POST /api/v1/icerik/{icerikId}/video-sahneleri/kirp |
generate |
Free |
| Changes one scene's picture with an AI edit: body talepAnahtari, sira, duzeltme (5–300 characters; e.g. turn the background into a terrace at sunset). The scene's price is charged. | POST /api/v1/icerik/{icerikId}/video-sahnesi/duzelt |
generate |
Spends credits |
| Applies the same picture edit to every editable scene: body talepAnahtari, duzeltme. Charged per scene; a scene that fails stays as it was and its price is refunded. | POST /api/v1/icerik/{icerikId}/video-duzeltme/toplu |
generate |
Spends credits |
| Returns an edited scene to its previous version: body sira. | POST /api/v1/icerik/{icerikId}/video-sahnesi/onceki-surum |
generate |
Free |
| Finishes editing: the scenes' previous versions are deleted and you can no longer go back. | POST /api/v1/icerik/{icerikId}/video-duzeltme/tamamla |
generate |
Free |
| Regenerates a scene with new text: a scene that failed, or a successful scene of a delivered video (as an edit; its previous version is kept and can be restored with the previous-version endpoint). Body talepAnahtari, sira, tarif and optional karakterler, sozler, mekan (the same rules as the scene fields of the generation request). The scene's price is charged again. | POST /api/v1/icerik/{icerikId}/video-sahnesi/yeniden-uret |
generate |
Spends credits |
| Drops the scenes that failed and assembles the video from the remaining scenes (no body). | POST /api/v1/icerik/{icerikId}/video-sahnesi/birlestir |
generate |
Free |
| Turns automatic cutting on or off: body acik (true or false). Only for a long video without background music (otherwise 409); the video is rebuilt once and manually trimmed scenes stay as they are; sending the current value does nothing. In the content details, videoSunumu.otomatikKesme gives the current choice. | PUT /api/v1/icerik/{icerikId}/video/otomatik-kesme |
generate |
Free |
| A video's subtitle cues in one language: start, end and text. | GET /api/v1/icerik/{icerikId}/alt-yazi/{dil} |
read |
Free |
| Edits the subtitle texts: body metinler; the same number and order as the cues, at most 200 characters each. Timings are kept. | PUT /api/v1/icerik/{icerikId}/alt-yazi/{dil} |
generate |
Free |
| A video's subtitles in one language as a WebVTT file (by the video's media ID). | GET /api/v1/medya/{medyaId}/altyazi/{dil} |
read |
Free |
| Preview of the end card added to the video (PNG), with the client's logo and brand color. | GET /api/v1/medya/kapanis-karti |
generate |
Free |
In the editing endpoints sira is the scene's position and starts at 0 (the first scene is 0); character and location numbers in the generation request start at 1. In the editing endpoints talepAnahtari is a UUID; in the generation request it may be any text up to 80 characters.
Automatic cutting: each scene is generated as a separate clip and ClientPoster joins the clips in order; at scene boundaries the sound joins with a short fade. In a long video with automatic cutting on, for scenes with speech, editing trims the silence at the start and end of the clip: sound is measured as the average of 50 ms windows, and a stretch below -33 dB lasting at least 0.6 s counts as silence; 0.3 s is kept before and 0.6 s after the speech, pauses inside sentences are left alone, and nothing is trimmed if less than 1 s would remain. The otomatikKesme field of the generation request controls this: empty means on, false turns it off (the clips are joined as they are); true is accepted only for a long video without background music (400 while fonMuzigi is soft). Short videos, scenes without speech and videos with background music are not cut. After delivery, change it free of charge with the otomatikKesme endpoint. To set a scene's range yourself, use manual trimming; on that scene it replaces automatic cutting.
Operations that change the video (trimming, editing, previous version, regenerating, assembling) run in the background: the response returns at once and the new video appears in the content details when it is ready (poll the content's detail endpoint). One edit runs at a time: a new edit while one is running gets 409. Content awaiting client approval cannot be edited.
9. Machine-readable API definition
All operations, fields, responses and permissions are available in OpenAPI 3.1 format at: https://api.clientposter.com/openapi/v1.json
If you work with an AI assistant, give it this address; enter your key only in the assistant's secret settings, never in the chat.