ShadowPhone
Content Generation API
This is the public step-by-step reference for the content-generation API onhttps://www.shadowphone.io/api/content-api/*. Your personal content API key maps to your own ShadowPhone account and uses the same credit balance and backend job system as the Telegram mini app.
Per-user key
Your personal content API key belongs to your own ShadowPhone account and should be treated like a password.
Same credits
API jobs use the same credits and charging rules as the ShadowPhone app and Telegram mini app.
Shared backend
Workflow listing, job creation, polling, save/delete behavior, and credit checks all reuse the same backend path.
How to get your key
- Open @shadowphone_bot and sign up or log in through the Telegram mini app.
- Open the Profile tab in the mini app, or go to your website profile/settings page.
- Find the Personal Content API Key card tied to your account.
- Use Reveal or Copy to access the current plaintext value temporarily.
- Use Rotate if you need a new key. Rotating revokes the prior active personal content key.
The preferred key format is sp_cpk_.... You can also call the content API with a broader sp_mcp_... key if it includes content:read and content:write.
Authentication
Send the key in the bearer header or with X-API-Key.
curl "https://www.shadowphone.io/api/content-api/workflows" \
-H "Authorization: Bearer sp_cpk_YOUR_PERSONAL_KEY"Supported headers: Authorization: Bearer ... or X-API-Key: ...
Key endpoints
/api/content-api/workflows/api/content-api/credits/api/content-api/uploads/api/content-api/jobs/api/content-api/jobs/:jobId/api/content-api/jobs/:jobId/cancel/api/content-api/jobs/:jobId/save/api/content-api/saved/api/content-api/saved/:outputIdUpload-first flow
The content API uses an upload-first pattern. Request upload targets, upload your files, then create the job using the returned hosted asset URLs. Use canonical asset field names in job payloads:image_url,video_url, andsecondary_image_url. Bulk usage today means scripting repeated upload and job calls — there is no dedicated bulk endpoint yet.
# 1) Request signed upload targets
curl -X POST "https://www.shadowphone.io/api/content-api/uploads" \
-H "Authorization: Bearer sp_cpk_YOUR_PERSONAL_KEY" \
-H "Content-Type: application/json" \
-d '{
"filename": "face.jpg",
"contentType": "image/jpeg"
}'
# 2) Upload bytes to the returned uploadUrl
# 3) Create the job with hosted asset URLs
curl -X POST "https://www.shadowphone.io/api/content-api/jobs" \
-H "Authorization: Bearer sp_cpk_YOUR_PERSONAL_KEY" \
-H "Content-Type: application/json" \
-d '{
"workflowType": "character_replace_v2",
"image_url": "https://.../face.jpg",
"video_url": "https://.../clip.mp4"
}'Featured workflows
character_replace_v2
Character Replace V2
Face image + target video. Default prep behavior applies if prep params are omitted.
gemini_nano_banana_pro
Image Gen Max
Primary image + secondary reference image, using the same image-generation path as the mini app.
nsfw_head_swap
Head Swap
Primary face image + secondary base image.
Workflow request examples
These examples use the canonical request field names for the public content API on https://www.shadowphone.io.
character_replace
Use when you want to provide a source image plus a target video on the original character-replace path.
curl -X POST "https://www.shadowphone.io/api/content-api/jobs" \
-H "Authorization: Bearer sp_cpk_YOUR_PERSONAL_KEY" \
-H "Content-Type: application/json" \
-d '{
"workflowType": "character_replace",
"image_url": "https://cdn.example.com/source-face.jpg",
"video_url": "https://cdn.example.com/target-video.mp4"
}'character_replace_v2
Use when you want to provide a source image plus a target video on the current V2 path.
curl -X POST "https://www.shadowphone.io/api/content-api/jobs" \
-H "Authorization: Bearer sp_cpk_YOUR_PERSONAL_KEY" \
-H "Content-Type: application/json" \
-d '{
"workflowType": "character_replace_v2",
"image_url": "https://cdn.example.com/source-face.jpg",
"video_url": "https://cdn.example.com/target-video.mp4"
}'motion_transfer_v2
Use when you want to animate a source image using the motion from a target video.
curl -X POST "https://www.shadowphone.io/api/content-api/jobs" \
-H "Authorization: Bearer sp_cpk_YOUR_PERSONAL_KEY" \
-H "Content-Type: application/json" \
-d '{
"workflowType": "motion_transfer_v2",
"image_url": "https://cdn.example.com/source-image.jpg",
"video_url": "https://cdn.example.com/motion-video.mp4"
}'video_motion
Use when you want to run the original motion-transfer style video path.
curl -X POST "https://www.shadowphone.io/api/content-api/jobs" \
-H "Authorization: Bearer sp_cpk_YOUR_PERSONAL_KEY" \
-H "Content-Type: application/json" \
-d '{
"workflowType": "video_motion",
"image_url": "https://cdn.example.com/source-image.jpg",
"video_url": "https://cdn.example.com/motion-video.mp4"
}'gemini_nano_banana_pro
Use when the workflow needs a primary image plus a secondary reference image.
curl -X POST "https://www.shadowphone.io/api/content-api/jobs" \
-H "Authorization: Bearer sp_cpk_YOUR_PERSONAL_KEY" \
-H "Content-Type: application/json" \
-d '{
"workflowType": "gemini_nano_banana_pro",
"image_url": "https://cdn.example.com/input-primary.jpg",
"secondary_image_url": "https://cdn.example.com/input-secondary.jpg"
}'gemini_image_remaker
Use when you want to remake a single input image with the Gemini remaker path.
curl -X POST "https://www.shadowphone.io/api/content-api/jobs" \
-H "Authorization: Bearer sp_cpk_YOUR_PERSONAL_KEY" \
-H "Content-Type: application/json" \
-d '{
"workflowType": "gemini_image_remaker",
"image_url": "https://cdn.example.com/input-image.jpg"
}'outfit_changer
Use when you want to provide a person image plus a second image for the target outfit.
curl -X POST "https://www.shadowphone.io/api/content-api/jobs" \
-H "Authorization: Bearer sp_cpk_YOUR_PERSONAL_KEY" \
-H "Content-Type: application/json" \
-d '{
"workflowType": "outfit_changer",
"image_url": "https://cdn.example.com/person-image.jpg",
"secondary_image_url": "https://cdn.example.com/outfit-image.jpg"
}'nsfw_head_swap
Use when the workflow needs a face image and a second base image.
curl -X POST "https://www.shadowphone.io/api/content-api/jobs" \
-H "Authorization: Bearer sp_cpk_YOUR_PERSONAL_KEY" \
-H "Content-Type: application/json" \
-d '{
"workflowType": "nsfw_head_swap",
"image_url": "https://cdn.example.com/source-face.jpg",
"secondary_image_url": "https://cdn.example.com/target-base.jpg"
}'skin_oiler
Use when you want to apply the skin-oiler effect to a single image.
curl -X POST "https://www.shadowphone.io/api/content-api/jobs" \
-H "Authorization: Bearer sp_cpk_YOUR_PERSONAL_KEY" \
-H "Content-Type: application/json" \
-d '{
"workflowType": "skin_oiler",
"image_url": "https://cdn.example.com/input-image.jpg"
}'Credits still apply to API jobs
Your personal content API key maps to your own ShadowPhone account, and API jobs still consume the same credits as work run from the Telegram mini app or app UI. The API does not create a separate credit wallet.
Use GET /api/content-api/credits before and after running work if you want to inspect your current credit snapshot.
Bulk usage and output destinations
Bulk usage today means scripting repeated upload and job calls. There is no dedicated bulk endpoint onhttps://www.shadowphone.io/api/content-api/*.
The recommended pattern is to upload many assets first with repeatedPOST /api/content-api/uploadscalls, keep the returned hosted asset URLs, and then create explicit jobs withPOST /api/content-api/jobsusing canonical fields such asimage_url,video_url, andsecondary_image_url.
Completed jobs return output locations viaresult_urlorresult_urls. Outputs can optionally be saved back into ShadowPhone withPOST /api/content-api/jobs/:jobId/save, and if your account is linked to Telegram they are also delivered to Telegram automatically through the same backend path used by the mini app.
Local disk and Google Drive are not built-in output sinks. If you want files in those destinations, your own script should download the returned output URLs and then upload or store them wherever you need.