Getting started
Introduction
The Silent Tech API turns a single word or short phrase into a cinematic, multi-frame text cut animation. Each request returns a JSON description of the animation — including the rendered passages with your word highlighted — plus an embeddable URL that plays the animation directly in any browser.
Base URL: https://devils.studio/api
All endpoints accept and return application/json. CORS is permissive (*) so you can call the API directly from a browser, a server, or a serverless function.
Security
Authentication
There is no authentication. You do not need an API key, an OAuth token, or an account. Silent Tech is designed to stay fully open and free — that is the entire product.
If you embed the player on a public site we ask (but don't require) that you keep the small devils.studio badge visible so others can find the project.
Fair use
Rate limits
There are no per-key rate limits because there are no keys. We apply a soft global limit at the edge to keep the service healthy for everyone — in normal use you will never hit it. If you plan to generate thousands of animations per minute (for example, a batch pipeline), please cache responses by their id field. Identical inputs always produce the same animation.
Reference
Errors
Errors return a non-2xx status code and a JSON body of the shape { "error": "human-readable message" }.
| Status | Message | Cause |
|---|---|---|
| 400 | Field "word" is required. | No word/phrase was provided. |
| 400 | Field "word" must be 60 characters or fewer. | Phrase too long. |
| 400 | Invalid JSON body. | POST body could not be parsed as JSON. |
| 405 | Method not allowed. | Use GET or POST on /api/animate. |
Endpoints
POST /api/animate
Generate an animation configuration for a given word or phrase. The response includes the resolved frames (already populated with your word) and a ready-to-use embed URL.
Request body
wordstylepaper, classic, documentary, editorial, noir, cinema.durationMsdurationMs: 4000 on the paper style yields 24 frames at ~6fps). Max 10000 (10s).durationdurationMs in seconds. Example: duration: 6 ≡ durationMs: 6000.framesdurationMs / duration. Clamped to 6..120.aspect16:9, 9:16, 1:1, 4:5.Example response
{
"id": "stx_2k1p4w8_classic_4",
"word": "horizon",
"style": "paper",
"aspect": "1:1",
"frames": [
{
"index": 0,
"text": "Across the bustling markets ... the spirit of horizon echoes ...",
"highlight": "#f7e935",
"durationMs": 170,
"category": "editorial"
},
{ "index": 1, "text": "...", "highlight": "#f7e935", "durationMs": 170, "category": "narrative" }
],
"totalDurationMs": 4080,
"embedUrl": "https://devils.studio/embed?word=horizon&style=paper&aspect=1%3A1&frames=24"
}Response fields
idid.wordstyleaspectframesindex, text (with the word highlighted in context), highlight color, durationMs, and a category tag.totalDurationMsembedUrlEndpoints
GET /api/animate
Identical to the POST endpoint but accepts the same parameters as query strings. Useful for quick links, webhooks, and curl.
curl 'https://devils.studio/api/animate?word=horizon&style=paper&durationMs=4000&aspect=1:1'Endpoints
GET /api/styles
Returns the list of available animation styles, including their default aspect ratios, frame durations, and highlight colors.
{
"object": "list",
"data": [
{ "id": "classic", "name": "Classic", "frameMs": 1600, "aspect": "9:16", "highlight": "#d4ff3a", ... },
{ "id": "documentary", "name": "Documentary", "frameMs": 2200, "aspect": "16:9", "highlight": "#ffd24a", ... },
{ "id": "editorial", "name": "Editorial", "frameMs": 1300, "aspect": "4:5", "highlight": "#ff5e3a", ... },
{ "id": "noir", "name": "Noir", "frameMs": 1800, "aspect": "1:1", "highlight": "#e6e6e6", ... },
{ "id": "cinema", "name": "Cinema", "frameMs": 2000, "aspect": "16:9", "highlight": "#3acfff", ... }
]
}Endpoints
GET /api/passages
Returns the full library of passage templates used by the animation engine. Useful if you want to inspect what kind of copy the engine pulls from before generating.
{
"object": "list",
"data": [
{ "id": "editorial-01", "category": "editorial", "body": "Across the bustling markets ... {word} ..." },
{ "id": "tech-01", "category": "tech", "body": "Analysts predict that {word} ..." },
...
]
}Embedding
Embeddable player
Every animation has a public, no-auth embed URL of the form /embed?word=.... Drop it into an iframe and you have a self-contained text cut player that runs purely in the browser.
<iframe
src="https://devils.studio/embed?word=horizon&style=paper&aspect=1:1&frames=24"
title="Silent Tech animation"
width="540"
height="540"
loading="lazy"
style="border:0;border-radius:16px"
></iframe>Embedding
Embed query parameters
wordstyleaspect16:9, 9:16, 1:1, or 4:5.framesbrandingoff to hide the small devils.studio badge.Examples
Code examples
Copy-paste snippets for the most common stacks. Replace the host with your local dev server during development.
Example
cURL
curl -X POST https://devils.studio/api/animate \
-H "content-type: application/json" \
-d '{
"word": "horizon",
"style": "paper",
"durationMs": 4000,
"aspect": "1:1"
}'Example
Node.js
// Node.js 18+ (uses built-in fetch)
const res = await fetch('https://devils.studio/api/animate', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({
word: 'horizon',
style: 'paper',
durationMs: 4000,
aspect: '1:1',
}),
})
if (!res.ok) {
throw new Error(`Animate failed: ${res.status}`)
}
const animation = await res.json()
console.log(animation.embedUrl)Example
Python
# Python 3.8+
import requests
resp = requests.post(
"https://devils.studio/api/animate",
json={
"word": "horizon",
"style": "paper",
"durationMs": 4000,
"aspect": "1:1",
},
timeout=10,
)
resp.raise_for_status()
animation = resp.json()
print(animation["embedUrl"])Example
React
// Drop-in React component using the Silent Tech embed
export function WordAnimation({ word }: { word: string }) {
const url = new URL('https://devils.studio/embed')
url.searchParams.set('word', word)
url.searchParams.set('style', 'paper')
url.searchParams.set('aspect', '1:1')
url.searchParams.set('frames', '24')
return (
<iframe
src={url.toString()}
title={`Silent Tech animation for ${word}`}
className="aspect-square w-full rounded-2xl border-0"
loading="lazy"
allow="autoplay"
/>
)
}Need a feature that's missing?
Silent Tech is open and intentionally small. If you want a new style, a new aspect, or a server-side MP4 renderer, open an issue — we'd love to hear from you.
Open an issue