# Audio & Voice API Overview
Source: https://docs.percify.io/api-reference/audio/overview
Clone voices and generate natural speech with multi-language support
## Overview
The Audio API provides voice cloning and text-to-speech capabilities. Clone voices from audio samples and generate natural-sounding speech in 30+ languages. Perfect for voiceovers, audiobooks, virtual assistants, and character dialogue.
## Base URL
```
https://api.percify.io/v1
```
## Core Endpoints
| Method | Endpoint | Description |
| ------ | ------------------- | ----------------------------- |
| POST | `/voices/clone` | Clone voice from audio sample |
| GET | `/voices` | List your voice clones |
| GET | `/voices/{voiceId}` | Get voice clone details |
| DELETE | `/voices/{voiceId}` | Delete voice clone |
| POST | `/audio/generate` | Generate speech from text |
| GET | `/audio/{audioId}` | Get audio generation status |
| GET | `/audio` | List generated audio files |
## Voice Clone Object
```json theme={null}
{
"id": "voice_abc123",
"userId": "user_xyz789",
"name": "My Custom Voice",
"language": "en-US",
"status": "completed",
"sampleUrl": "https://cdn.percify.io/voices/voice_abc123_sample.mp3",
"sampleDuration": 45.3,
"quality": "high",
"creditCost": 5,
"metadata": {
"pitch": "medium",
"pace": "normal",
"emotion": "neutral"
},
"createdAt": "2025-11-25T06:20:00Z"
}
```
## Audio Generation Object
```json theme={null}
{
"id": "audio_def456",
"userId": "user_xyz789",
"voiceId": "voice_abc123",
"text": "Welcome to Percify! Your AI-powered creative platform.",
"status": "completed",
"audioUrl": "https://cdn.percify.io/audio/audio_def456.mp3",
"durationSeconds": 5.2,
"format": "mp3",
"sampleRate": 44100,
"bitrate": 192,
"creditCost": 10,
"language": "en-US",
"metadata": {
"speed": 1.0,
"pitch": 0,
"emotion": "neutral"
},
"createdAt": "2025-11-25T06:25:00Z",
"completedAt": "2025-11-25T06:25:03Z"
}
```
## Pricing
### Voice Cloning
* **Cost:** 5 credits per voice clone (one-time)
* **Reusable:** Generate unlimited audio with same voice ID
### Audio Generation
* **Base:** 5 credits
* **Duration:** +1 credit per second
* **Formula:** `Total = 5 + (duration_seconds × 1)`
### Examples
| Duration | Calculation | Total Credits |
| -------- | ------------- | ------------- |
| 5s | 5 + (5 × 1) | 10 |
| 15s | 5 + (15 × 1) | 20 |
| 60s | 5 + (60 × 1) | 65 |
| 2min | 5 + (120 × 1) | 125 |
## Quick Start
### Clone a Voice
```javascript Node.js theme={null}
const fs = require('fs');
const FormData = require('form-data');
const form = new FormData();
form.append('audio', fs.createReadStream('voice-sample.wav'));
form.append('name', 'Professional Narrator');
form.append('language', 'en-US');
const response = await fetch('https://api.percify.io/v1/voices/clone', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.PERCIFY_API_KEY}`,
...form.getHeaders()
},
body: form
});
const voice = await response.json();
console.log(`Voice ID: ${voice.id}`);
```
```python Python theme={null}
import os
import requests
with open('voice-sample.wav', 'rb') as audio_file:
files = {'audio': audio_file}
data = {
'name': 'Professional Narrator',
'language': 'en-US'
}
response = requests.post(
'https://api.percify.io/v1/voices/clone',
headers={'Authorization': f'Bearer {os.environ["PERCIFY_API_KEY"]}'},
files=files,
data=data
)
voice = response.json()
print(f"Voice ID: {voice['id']}")
```
```bash cURL theme={null}
curl -X POST https://api.percify.io/v1/voices/clone \
-H "Authorization: Bearer $PERCIFY_API_KEY" \
-F "audio=@voice-sample.wav" \
-F "name=Professional Narrator" \
-F "language=en-US"
```
### Generate Speech
```javascript Node.js theme={null}
const response = await fetch('https://api.percify.io/v1/audio/generate', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.PERCIFY_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
text: 'Welcome to Percify! Your AI-powered creative platform.',
voiceId: 'voice_abc123',
speed: 1.0,
outputFormat: 'mp3'
})
});
const audio = await response.json();
console.log(`Audio URL: ${audio.audioUrl}`);
```
```python Python theme={null}
import os
import requests
response = requests.post(
'https://api.percify.io/v1/audio/generate',
headers={
'Authorization': f'Bearer {os.environ["PERCIFY_API_KEY"]}',
'Content-Type': 'application/json'
},
json={
'text': 'Welcome to Percify! Your AI-powered creative platform.',
'voiceId': 'voice_abc123',
'speed': 1.0,
'outputFormat': 'mp3'
}
)
audio = response.json()
print(f"Audio URL: {audio['audioUrl']}")
```
```bash cURL theme={null}
curl -X POST https://api.percify.io/v1/audio/generate \
-H "Authorization: Bearer $PERCIFY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "Welcome to Percify! Your AI-powered creative platform.",
"voiceId": "voice_abc123",
"speed": 1.0,
"outputFormat": "mp3"
}'
```
## Supported Languages
* `en-US` - American English
* `en-GB` - British English
* `en-AU` - Australian English
* `en-CA` - Canadian English
* `en-IN` - Indian English
* `es-ES` - Spanish (Spain)
* `es-MX` - Spanish (Mexico)
* `fr-FR` - French
* `de-DE` - German
* `it-IT` - Italian
* `pt-PT` - Portuguese (Portugal)
* `pt-BR` - Portuguese (Brazil)
* `pl-PL` - Polish
* `nl-NL` - Dutch
* `ru-RU` - Russian
* `zh-CN` - Mandarin (Simplified)
* `zh-TW` - Mandarin (Traditional)
* `ja-JP` - Japanese
* `ko-KR` - Korean
* `hi-IN` - Hindi
* `th-TH` - Thai
* `vi-VN` - Vietnamese
* `id-ID` - Indonesian
* `ar-SA` - Arabic
* `tr-TR` - Turkish
* `sv-SE` - Swedish
* `da-DK` - Danish
* `no-NO` - Norwegian
* `fi-FI` - Finnish
## Preset Voices
Use built-in voices without cloning:
| Voice ID | Description | Languages |
| ---------------------------- | ------------------- | ------------- |
| `preset-professional-male` | Deep, authoritative | All supported |
| `preset-professional-female` | Clear, confident | All supported |
| `preset-friendly-male` | Warm, approachable | All supported |
| `preset-friendly-female` | Upbeat, energetic | All supported |
| `preset-narrator` | Storytelling style | All supported |
## Voice Modulation
Control speech characteristics:
```javascript theme={null}
const audio = await client.audio.generate({
text: 'This is an exciting announcement!',
voiceId: 'voice_abc123',
// Speed control
speed: 1.1, // 0.5 to 2.0 (1.0 = normal)
// Pitch control
pitch: 2, // -10 to +10 semitones
// Emotion
emotion: 'excited', // neutral, happy, sad, excited, calm
// Emphasis
emphasis: ['exciting', 'announcement'],
// Output format
outputFormat: 'mp3', // mp3, wav, ogg
sampleRate: 44100, // 22050, 44100, 48000
bitrate: 192 // kbps for mp3
});
```
## Audio Quality Options
### Output Formats
| Format | Codec | Use Case | File Size |
| ------ | ------------------ | ------------------------------------- | --------- |
| MP3 | MPEG Audio Layer 3 | Web, streaming, general use | Small |
| WAV | Uncompressed PCM | Professional editing, highest quality | Large |
| OGG | Ogg Vorbis | Open format, web embedding | Medium |
### Sample Rates
* **22050 Hz:** Voice-only, minimal quality
* **44100 Hz:** CD quality, recommended for most uses
* **48000 Hz:** Professional audio, broadcast quality
## SSML Support
Use Speech Synthesis Markup Language for fine control:
```xml theme={null}
Welcome to Percify!
Create amazing content
with our AI-powered tools.
Let's get started!
```
```javascript theme={null}
const audio = await client.audio.generate({
text: ssmlContent,
voiceId: 'voice_abc123',
textFormat: 'ssml'
});
```
## Error Responses
```json theme={null}
{
"error": {
"code": "invalid_audio_sample",
"message": "Audio sample too short. Minimum 15 seconds required.",
"details": {
"duration": 8.3,
"minimum": 15,
"recommended": 30
}
}
}
```
Common error codes:
* `invalid_audio_sample` - Poor quality or too short
* `unsupported_language` - Language not available
* `text_too_long` - Exceeds maximum length (10,000 chars)
* `voice_not_found` - Voice ID doesn't exist
* `insufficient_credits` - Not enough credits
## Rate Limits
| Tier | Voice Cloning | Audio Generation | Concurrent |
| ---------- | ------------- | ---------------- | ---------- |
| Free | 5/day | 100/day | 2 |
| Pro | 50/day | 1000/day | 5 |
| Enterprise | Unlimited | Unlimited | 20 |
## Best Practices
For best voice cloning results:
* Use clean, noise-free environment
* 15-60 seconds of clear speech
* Professional microphone recommended
* Sample rate: 44.1kHz or higher
* Format: WAV, MP3, or FLAC
* Keep sentences natural and conversational
* Use punctuation for proper pauses
* Break long text into smaller chunks
* Specify pronunciation for technical terms
* Test with short samples first
* Only clone voices you have permission to use
* Don't impersonate without consent
* Clearly disclose AI-generated content
* Comply with local voice biometric laws
## Webhooks
Subscribe to audio completion events:
```json theme={null}
{
"event": "audio.completed",
"data": {
"audioId": "audio_def456",
"voiceId": "voice_abc123",
"audioUrl": "https://cdn.percify.io/audio/audio_def456.mp3",
"durationSeconds": 5.2,
"creditCost": 10
},
"timestamp": "2025-11-25T06:25:03Z"
}
```
## Next Steps
Create voice profiles
Text-to-speech
Sync with video
# Generate Avatar
Source: https://docs.percify.io/api-reference/avatars/generate
POST /avatars/generate
Create a new AI avatar from a text prompt
## Endpoint
```
POST https://api.percify.io/v1/avatars/generate
```
## Request Body
Text description of the desired avatar. Be specific about appearance, style, setting, and mood.
**Example:** `"cyberpunk warrior, neon lights, futuristic city, dramatic lighting"`
AI model to use for generation.
**Options:**
* `flux` - Fast, 2 credits (standard quality)
* `imagen3` - High quality, 5 credits
* `reality4` - Ultra realistic, 5 credits
Elements to avoid in the generation.
**Example:** `"blurry, low quality, distorted, extra limbs"`
Output image aspect ratio.
**Options:** `1:1`, `16:9`, `9:16`, `4:3`, `3:4`
How closely to follow the prompt (7-15 recommended).
**Range:** 1-20. Higher values = stricter adherence
Random seed for reproducible results. Use same seed with same prompt for identical output.
**Range:** 0 to 2147483647
Number of variations to generate simultaneously.
**Range:** 1-4. Each variation costs credits.
Apply a predefined style template.
**Options:** `professional`, `anime`, `fantasy`, `cyberpunk`, `renaissance`, `realistic`
## Response
Unique avatar identifier
Current generation status: `queued`, `processing`, `completed`, `failed`
The prompt used for generation
AI model used
Full resolution image URL (available when status = completed)
Thumbnail image URL (available when status = completed)
Image width in pixels
Image height in pixels
Credits deducted for this generation
ISO 8601 timestamp of creation
## Example Request
```javascript Node.js theme={null}
const response = await fetch('https://api.percify.io/v1/avatars/generate', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.PERCIFY_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
prompt: 'elegant elven sorceress, flowing robes, mystical forest, magical glow',
model: 'imagen3',
negativePrompt: 'blurry, low quality, distorted',
aspectRatio: '1:1',
guidanceScale: 12,
seed: 42
})
});
const avatar = await response.json();
console.log(avatar);
```
```python Python theme={null}
import os
import requests
response = requests.post(
'https://api.percify.io/v1/avatars/generate',
headers={
'Authorization': f'Bearer {os.environ["PERCIFY_API_KEY"]}',
'Content-Type': 'application/json'
},
json={
'prompt': 'elegant elven sorceress, flowing robes, mystical forest, magical glow',
'model': 'imagen3',
'negativePrompt': 'blurry, low quality, distorted',
'aspectRatio': '1:1',
'guidanceScale': 12,
'seed': 42
}
)
avatar = response.json()
print(avatar)
```
```bash cURL theme={null}
curl -X POST https://api.percify.io/v1/avatars/generate \
-H "Authorization: Bearer $PERCIFY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "elegant elven sorceress, flowing robes, mystical forest, magical glow",
"model": "imagen3",
"negativePrompt": "blurry, low quality, distorted",
"aspectRatio": "1:1",
"guidanceScale": 12,
"seed": 42
}'
```
## Example Response
### Processing (Immediate Response)
```json theme={null}
{
"id": "avatar_abc123",
"status": "processing",
"prompt": "elegant elven sorceress, flowing robes, mystical forest, magical glow",
"negativePrompt": "blurry, low quality, distorted",
"model": "imagen3",
"aspectRatio": "1:1",
"guidanceScale": 12,
"seed": 42,
"creditCost": 5,
"createdAt": "2025-11-25T06:10:00Z"
}
```
### Completed (After Polling)
```json theme={null}
{
"id": "avatar_abc123",
"status": "completed",
"prompt": "elegant elven sorceress, flowing robes, mystical forest, magical glow",
"negativePrompt": "blurry, low quality, distorted",
"model": "imagen3",
"imageUrl": "https://cdn.percify.io/avatars/avatar_abc123.png",
"thumbnailUrl": "https://cdn.percify.io/avatars/avatar_abc123_thumb.png",
"width": 1024,
"height": 1024,
"aspectRatio": "1:1",
"guidanceScale": 12,
"seed": 42,
"creditCost": 5,
"metadata": {
"generationTime": 7.8,
"modelVersion": "imagen3-v2.1"
},
"createdAt": "2025-11-25T06:10:00Z",
"completedAt": "2025-11-25T06:10:08Z"
}
```
## Error Responses
### Insufficient Credits
```json theme={null}
{
"error": {
"code": "insufficient_credits",
"message": "Not enough credits. Required: 5, Available: 2",
"details": {
"required": 5,
"available": 2,
"shortfall": 3
}
}
}
```
### Invalid Prompt
```json theme={null}
{
"error": {
"code": "invalid_prompt",
"message": "Prompt violates content policy",
"details": {
"reason": "prohibited_content",
"categories": ["violence"]
}
}
}
```
### Rate Limited
```json theme={null}
{
"error": {
"code": "rate_limit_exceeded",
"message": "Too many requests. Try again in 45 seconds",
"details": {
"retryAfter": 45,
"limit": 60,
"window": "1m"
}
}
}
```
## Polling for Completion
After initiating generation, poll the avatar status endpoint:
```javascript theme={null}
async function waitForAvatar(avatarId) {
const maxWait = 60000; // 60 seconds
const pollInterval = 2000; // 2 seconds
const startTime = Date.now();
while (Date.now() - startTime < maxWait) {
const response = await fetch(
`https://api.percify.io/v1/avatars/${avatarId}`,
{
headers: {
'Authorization': `Bearer ${process.env.PERCIFY_API_KEY}`
}
}
);
const avatar = await response.json();
if (avatar.status === 'completed') {
return avatar;
} else if (avatar.status === 'failed') {
throw new Error(`Generation failed: ${avatar.error}`);
}
await new Promise(resolve => setTimeout(resolve, pollInterval));
}
throw new Error('Avatar generation timed out');
}
// Usage
const avatar = await waitForAvatar('avatar_abc123');
console.log(`Avatar ready: ${avatar.imageUrl}`);
```
## Batch Generation
Generate multiple variations in parallel:
```javascript theme={null}
const response = await fetch('https://api.percify.io/v1/avatars/generate', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.PERCIFY_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
prompt: 'space explorer, futuristic helmet, stars background',
model: 'flux',
batchSize: 4 // Generate 4 variations
})
});
const result = await response.json();
// result.avatars = array of 4 avatar objects
```
Each variation in a batch costs credits. `batchSize: 4` with `model: 'flux'` = 8 credits total (4 × 2)
## Best Practices
**Prompt Engineering:** Be specific and descriptive. Good prompts include:
* Subject/character description
* Art style or aesthetic
* Setting and environment
* Lighting conditions
* Mood or emotion
**Cost Optimization:**
1. Start with `flux` model (2 credits) for iteration
2. Switch to premium models once prompt is refined
3. Use seeds to reproduce good results without regenerating
4. Batch similar prompts together for efficiency
## Related Endpoints
* [Get Avatar](/api-reference/avatars/get) - Check generation status
* [List Avatars](/api-reference/avatars/list) - View all your avatars
* [Publish Avatar](/api-reference/avatars/publish) - Share to community
# List Avatars
Source: https://docs.percify.io/api-reference/avatars/list
GET /avatars
Retrieve a paginated list of your avatars
## Endpoint
```
GET https://api.percify.io/v1/avatars
```
## Query Parameters
Number of avatars to return per page
**Range:** 1-100
Number of avatars to skip (for pagination)
**Example:** `offset=20` with `limit=20` returns avatars 21-40
Filter by generation status
**Options:** `queued`, `processing`, `completed`, `failed`
Filter by AI model used
**Options:** `flux`, `imagen3`, `reality4`
Filter by visibility setting
**Options:** `public`, `unlisted`, `private`
Filter by publication status
**Options:** `true` (published only), `false` (unpublished only)
Sort field
**Options:** `createdAt`, `likes`, `comments`, `remixes`
Sort direction
**Options:** `asc`, `desc`
Search avatars by prompt text or tags
**Example:** `search=cyberpunk`
## Response
Array of avatar objects
Pagination metadata
Total number of avatars matching filters
Items per page
Current offset
Whether more pages exist
## Example Request
```javascript Node.js theme={null}
const response = await fetch(
'https://api.percify.io/v1/avatars?limit=20&offset=0&status=completed&sortBy=createdAt&sortOrder=desc',
{
headers: {
'Authorization': `Bearer ${process.env.PERCIFY_API_KEY}`
}
}
);
const data = await response.json();
console.log(`Found ${data.pagination.total} avatars`);
data.avatars.forEach(avatar => {
console.log(`${avatar.id}: ${avatar.prompt}`);
});
```
```python Python theme={null}
import os
import requests
response = requests.get(
'https://api.percify.io/v1/avatars',
params={
'limit': 20,
'offset': 0,
'status': 'completed',
'sortBy': 'createdAt',
'sortOrder': 'desc'
},
headers={
'Authorization': f'Bearer {os.environ["PERCIFY_API_KEY"]}'
}
)
data = response.json()
print(f"Found {data['pagination']['total']} avatars")
for avatar in data['avatars']:
print(f"{avatar['id']}: {avatar['prompt']}")
```
```bash cURL theme={null}
curl -X GET "https://api.percify.io/v1/avatars?limit=20&offset=0&status=completed&sortBy=createdAt&sortOrder=desc" \
-H "Authorization: Bearer $PERCIFY_API_KEY"
```
## Example Response
```json theme={null}
{
"avatars": [
{
"id": "avatar_abc123",
"status": "completed",
"prompt": "cyberpunk warrior, neon lights, futuristic city",
"model": "imagen3",
"imageUrl": "https://cdn.percify.io/avatars/avatar_abc123.png",
"thumbnailUrl": "https://cdn.percify.io/avatars/avatar_abc123_thumb.png",
"width": 1024,
"height": 1024,
"creditCost": 5,
"visibility": "public",
"published": true,
"likes": 42,
"comments": 8,
"createdAt": "2025-11-25T06:00:00Z"
},
{
"id": "avatar_def456",
"status": "completed",
"prompt": "fantasy elf mage, magical forest, glowing staff",
"model": "flux",
"imageUrl": "https://cdn.percify.io/avatars/avatar_def456.png",
"thumbnailUrl": "https://cdn.percify.io/avatars/avatar_def456_thumb.png",
"width": 1024,
"height": 1024,
"creditCost": 2,
"visibility": "private",
"published": false,
"likes": 0,
"comments": 0,
"createdAt": "2025-11-25T05:45:00Z"
}
],
"pagination": {
"total": 156,
"limit": 20,
"offset": 0,
"hasMore": true
}
}
```
## Pagination Example
```javascript theme={null}
async function fetchAllAvatars() {
const allAvatars = [];
let offset = 0;
const limit = 50;
let hasMore = true;
while (hasMore) {
const response = await fetch(
`https://api.percify.io/v1/avatars?limit=${limit}&offset=${offset}`,
{
headers: {
'Authorization': `Bearer ${process.env.PERCIFY_API_KEY}`
}
}
);
const data = await response.json();
allAvatars.push(...data.avatars);
hasMore = data.pagination.hasMore;
offset += limit;
}
return allAvatars;
}
```
## Filtering Examples
### Get Published Avatars Only
```bash theme={null}
curl "https://api.percify.io/v1/avatars?published=true&visibility=public" \
-H "Authorization: Bearer $PERCIFY_API_KEY"
```
### Search by Keyword
```bash theme={null}
curl "https://api.percify.io/v1/avatars?search=fantasy&limit=10" \
-H "Authorization: Bearer $PERCIFY_API_KEY"
```
### Get Most Liked Avatars
```bash theme={null}
curl "https://api.percify.io/v1/avatars?sortBy=likes&sortOrder=desc&limit=10" \
-H "Authorization: Bearer $PERCIFY_API_KEY"
```
### Get Processing Avatars
```bash theme={null}
curl "https://api.percify.io/v1/avatars?status=processing" \
-H "Authorization: Bearer $PERCIFY_API_KEY"
```
## Related Endpoints
* [Get Avatar](/api-reference/avatars/get) - Get single avatar details
* [Generate Avatar](/api-reference/avatars/generate) - Create new avatar
* [Delete Avatar](/api-reference/avatars/delete) - Remove avatar
# Avatar API Overview
Source: https://docs.percify.io/api-reference/avatars/overview
Comprehensive API for creating, managing, and publishing AI avatars
## Overview
The Avatar API provides endpoints for generating AI avatars, managing avatar metadata, publishing to the community feed, and retrieving avatar assets. All endpoints require authentication via API key.
## Base URL
```
https://api.percify.io/v1
```
## Authentication
All requests must include your API key in the Authorization header:
```bash theme={null}
Authorization: Bearer YOUR_API_KEY
```
## Core Endpoints
| Method | Endpoint | Description |
| ------ | ----------------------------- | --------------------------------- |
| POST | `/avatars/generate` | Generate a new avatar from prompt |
| POST | `/avatars/percify-yourself` | Create avatar from photo |
| POST | `/avatars/cast` | Generate multi-character scene |
| GET | `/avatars/{avatarId}` | Get avatar details |
| GET | `/avatars` | List your avatars |
| PATCH | `/avatars/{avatarId}` | Update avatar metadata |
| POST | `/avatars/{avatarId}/publish` | Publish avatar to feed |
| DELETE | `/avatars/{avatarId}` | Delete avatar |
| POST | `/avatars/{avatarId}/like` | Like an avatar |
| POST | `/avatars/{avatarId}/comment` | Comment on avatar |
| POST | `/avatars/{avatarId}/remix` | Remix/derive from avatar |
## Avatar Object
```json theme={null}
{
"id": "avatar_abc123",
"userId": "user_xyz789",
"status": "completed",
"prompt": "cyberpunk warrior, neon lights, futuristic city",
"negativePrompt": "blurry, low quality",
"model": "imagen3",
"imageUrl": "https://cdn.percify.io/avatars/avatar_abc123.png",
"thumbnailUrl": "https://cdn.percify.io/avatars/avatar_abc123_thumb.png",
"width": 1024,
"height": 1024,
"aspectRatio": "1:1",
"guidanceScale": 12,
"seed": 42,
"creditCost": 5,
"visibility": "public",
"published": true,
"publishedAt": "2025-11-25T06:00:00Z",
"likes": 42,
"comments": 8,
"remixes": 3,
"tags": ["cyberpunk", "character", "warrior"],
"metadata": {
"generationTime": 7.3,
"modelVersion": "imagen3-v2.1"
},
"createdAt": "2025-11-25T05:59:52Z",
"updatedAt": "2025-11-25T06:00:00Z"
}
```
## Quick Start Examples
### Generate Basic Avatar
```javascript Node.js theme={null}
const response = await fetch('https://api.percify.io/v1/avatars/generate', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.PERCIFY_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
prompt: 'fantasy elf warrior, forest background, magical aura',
model: 'flux',
aspectRatio: '1:1'
})
});
const avatar = await response.json();
console.log(`Avatar ID: ${avatar.id}`);
```
```python Python theme={null}
import os
import requests
response = requests.post(
'https://api.percify.io/v1/avatars/generate',
headers={
'Authorization': f'Bearer {os.environ["PERCIFY_API_KEY"]}',
'Content-Type': 'application/json'
},
json={
'prompt': 'fantasy elf warrior, forest background, magical aura',
'model': 'flux',
'aspectRatio': '1:1'
}
)
avatar = response.json()
print(f"Avatar ID: {avatar['id']}")
```
```bash cURL theme={null}
curl -X POST https://api.percify.io/v1/avatars/generate \
-H "Authorization: Bearer $PERCIFY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "fantasy elf warrior, forest background, magical aura",
"model": "flux",
"aspectRatio": "1:1"
}'
```
### Get Avatar Status
```bash theme={null}
curl -X GET https://api.percify.io/v1/avatars/avatar_abc123 \
-H "Authorization: Bearer $PERCIFY_API_KEY"
```
### List Your Avatars
```bash theme={null}
curl -X GET https://api.percify.io/v1/avatars?limit=20&offset=0 \
-H "Authorization: Bearer $PERCIFY_API_KEY"
```
## Generation Status
Avatars go through several status stages:
| Status | Description | Next Action |
| ------------ | --------------------------- | ---------------------- |
| `queued` | Waiting in generation queue | Poll for status update |
| `processing` | AI model is generating | Continue polling |
| `completed` | Generation successful | Image URLs available |
| `failed` | Generation failed | Check error details |
## Error Responses
Standard error format:
```json theme={null}
{
"error": {
"code": "insufficient_credits",
"message": "Not enough credits to generate avatar. Required: 5, Available: 2",
"details": {
"required": 5,
"available": 2
}
}
}
```
Common error codes:
* `invalid_request` - Missing or invalid parameters
* `authentication_required` - Missing or invalid API key
* `insufficient_credits` - Not enough credits for operation
* `rate_limit_exceeded` - Too many requests
* `content_policy_violation` - Prompt violates content policy
* `avatar_not_found` - Avatar ID doesn't exist
* `unauthorized_access` - Can't access another user's private avatar
## Rate Limits
| Tier | Requests/minute | Concurrent Generations |
| ---------- | --------------- | ---------------------- |
| Free | 10 | 1 |
| Pro | 60 | 5 |
| Enterprise | 300 | 20 |
Rate limit headers included in responses:
```
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1700000000
```
## Webhooks
Subscribe to avatar events:
```json theme={null}
{
"event": "avatar.completed",
"data": {
"avatarId": "avatar_abc123",
"status": "completed",
"imageUrl": "https://cdn.percify.io/avatars/avatar_abc123.png"
},
"timestamp": "2025-11-25T06:00:00Z"
}
```
Available events:
* `avatar.completed` - Generation finished successfully
* `avatar.failed` - Generation failed
* `avatar.published` - Avatar published to feed
* `avatar.liked` - Someone liked your avatar
* `avatar.commented` - New comment on avatar
## Best Practices
```javascript theme={null}
async function waitForAvatar(avatarId) {
const maxAttempts = 30;
const pollInterval = 2000; // 2 seconds
for (let i = 0; i < maxAttempts; i++) {
const response = await fetch(
`https://api.percify.io/v1/avatars/${avatarId}`,
{
headers: {
'Authorization': `Bearer ${process.env.PERCIFY_API_KEY}`
}
}
);
const avatar = await response.json();
if (avatar.status === 'completed') {
return avatar;
} else if (avatar.status === 'failed') {
throw new Error(`Generation failed: ${avatar.error}`);
}
await new Promise(resolve => setTimeout(resolve, pollInterval));
}
throw new Error('Avatar generation timed out');
}
```
Use idempotency keys for safe retries:
```bash theme={null}
curl -X POST https://api.percify.io/v1/avatars/generate \
-H "Authorization: Bearer $PERCIFY_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: unique-key-123" \
-d '{"prompt": "..."}'
```
```javascript theme={null}
try {
const response = await fetch('https://api.percify.io/v1/avatars/generate', {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ prompt, model })
});
if (!response.ok) {
const error = await response.json();
if (error.error.code === 'insufficient_credits') {
// Handle low credits
console.log('Please purchase more credits');
} else if (error.error.code === 'rate_limit_exceeded') {
// Wait and retry
const resetTime = response.headers.get('X-RateLimit-Reset');
console.log(`Rate limited until ${new Date(resetTime * 1000)}`);
} else {
throw new Error(error.error.message);
}
}
const avatar = await response.json();
return avatar;
} catch (error) {
console.error('Avatar generation failed:', error);
throw error;
}
```
## Next Steps
Create new avatars
List and organize
Share with community
## Support
Questions about the Avatar API? Check our [FAQ](/percify/faq) or contact [support@percify.io](mailto:support@percify.io).
# Percify API Overview
Source: https://docs.percify.io/api-reference/introduction
Core concepts, authentication, and response patterns
## Purpose
The Percify API lets you programmatically generate images, transform them into videos, synthesize voice audio, and retrieve published media assets. All endpoints follow predictable credit-based metering.
## Base URL
```
https://api.percify.io/v1
```
## Authentication
Use an API key in the `Authorization` header:
```
Authorization: Bearer
```
Keys are scoped per user account. Rotate periodically and never embed client-side.
## Common Endpoints
| Action | Method | Path |
| ---------------- | ------ | ------------------- |
| Generate Image | POST | /images/generate |
| Video From Image | POST | /videos/from-image |
| Clone Voice | POST | /voices/clone |
| Generate Audio | POST | /audio/generate |
| Avatar Metadata | GET | /avatars/{avatarId} |
| Credit Balance | GET | /credits/balance |
## Response Pattern
Successful async generation requests return a processing object:
```json theme={null}
{
"id": "img_123",
"status": "processing",
"creditCost": 5,
"createdAt": "2025-11-24T12:34:56Z"
}
```
Poll the status endpoint (same resource path) until `status` becomes `completed`.
## Errors
| Status | Meaning | Typical Cause |
| ------ | ------------ | ----------------------------------------- |
| 400 | Bad request | Missing required field / invalid duration |
| 401 | Unauthorized | Missing or bad API key |
| 403 | Forbidden | Banned user or restricted asset |
| 404 | Not found | Invalid resource id |
| 429 | Rate limited | Too many requests in window |
| 500 | Server error | Internal failure; retry later |
## Idempotency (Recommended)
For operations that could be retried (e.g., payment intent creation), include an `Idempotency-Key` header. Future endpoints may enforce uniqueness for safety.
## Webhooks (Planned)
Upcoming event types:
* `avatar.generated`
* `video.completed`
* `audio.completed`
* `credits.updated`
## OpenAPI Specification
The full schema resides in `api-reference/openapi.json`. Use it to generate client SDKs or validate requests.
## Next Steps
* Review authentication details at \[/percify/api-auth]
* Explore endpoint examples in the API Reference tab
* Learn credit cost formulas at \[/percify/credits]
***
Need a new endpoint? Request via support with use case details.
# User & Credits API
Source: https://docs.percify.io/api-reference/user/overview
Manage user profiles, credit balance, and usage tracking
## Overview
The User & Credits API provides endpoints for managing user profiles, checking credit balance, viewing usage history, and handling billing operations.
## Base URL
```
https://api.percify.io/v1
```
## Core Endpoints
| Method | Endpoint | Description |
| ------ | ------------------------ | ------------------------------ |
| GET | `/user/profile` | Get current user profile |
| PATCH | `/user/profile` | Update user profile |
| GET | `/user/credits/balance` | Get credit balance |
| GET | `/user/credits/history` | Get credit transaction history |
| GET | `/user/usage` | Get usage statistics |
| POST | `/user/credits/purchase` | Purchase credit pack |
| GET | `/user/tier` | Get subscription tier info |
## User Profile Object
```json theme={null}
{
"id": "user_abc123",
"email": "user@example.com",
"username": "creative_user",
"displayName": "Creative User",
"avatar": "https://cdn.percify.io/avatars/user_abc123.jpg",
"bio": "AI artist and content creator",
"website": "https://example.com",
"tier": "pro",
"verified": true,
"stats": {
"avatarsCreated": 156,
"videosGenerated": 42,
"voicesCloned": 8,
"followers": 234,
"following": 89
},
"createdAt": "2025-01-15T10:00:00Z",
"updatedAt": "2025-11-25T06:30:00Z"
}
```
## Credits Object
```json theme={null}
{
"balance": 450,
"lifetime": {
"earned": 50,
"purchased": 500,
"spent": 100
},
"currentMonth": {
"earned": 0,
"spent": 35
},
"tier": "pro",
"nextRefill": "2025-12-01T00:00:00Z"
}
```
## Get User Profile
```javascript Node.js theme={null}
const response = await fetch('https://api.percify.io/v1/user/profile', {
headers: {
'Authorization': `Bearer ${process.env.PERCIFY_API_KEY}`
}
});
const profile = await response.json();
console.log(`Username: ${profile.username}, Tier: ${profile.tier}`);
```
```python Python theme={null}
import os
import requests
response = requests.get(
'https://api.percify.io/v1/user/profile',
headers={'Authorization': f'Bearer {os.environ["PERCIFY_API_KEY"]}'}
)
profile = response.json()
print(f"Username: {profile['username']}, Tier: {profile['tier']}")
```
```bash cURL theme={null}
curl -X GET https://api.percify.io/v1/user/profile \
-H "Authorization: Bearer $PERCIFY_API_KEY"
```
## Get Credit Balance
```javascript Node.js theme={null}
const response = await fetch('https://api.percify.io/v1/user/credits/balance', {
headers: {
'Authorization': `Bearer ${process.env.PERCIFY_API_KEY}`
}
});
const credits = await response.json();
console.log(`Available credits: ${credits.balance}`);
```
```python Python theme={null}
import os
import requests
response = requests.get(
'https://api.percify.io/v1/user/credits/balance',
headers={'Authorization': f'Bearer {os.environ["PERCIFY_API_KEY"]}'}
)
credits = response.json()
print(f"Available credits: {credits['balance']}")
```
```bash cURL theme={null}
curl -X GET https://api.percify.io/v1/user/credits/balance \
-H "Authorization: Bearer $PERCIFY_API_KEY"
```
## Credit Transaction History
```bash theme={null}
curl "https://api.percify.io/v1/user/credits/history?limit=50&offset=0" \
-H "Authorization: Bearer $PERCIFY_API_KEY"
```
Response:
```json theme={null}
{
"transactions": [
{
"id": "txn_abc123",
"type": "debit",
"amount": 5,
"balance": 445,
"description": "Avatar generation (Imagen3)",
"resourceType": "avatar",
"resourceId": "avatar_xyz789",
"createdAt": "2025-11-25T06:15:00Z"
},
{
"id": "txn_def456",
"type": "credit",
"amount": 100,
"balance": 450,
"description": "Credit pack purchase",
"resourceType": "purchase",
"resourceId": "purchase_pqr012",
"createdAt": "2025-11-20T14:30:00Z"
}
],
"pagination": {
"total": 234,
"limit": 50,
"offset": 0,
"hasMore": true
}
}
```
## Usage Statistics
```bash theme={null}
curl "https://api.percify.io/v1/user/usage?period=30d" \
-H "Authorization: Bearer $PERCIFY_API_KEY"
```
Response:
```json theme={null}
{
"period": "30d",
"startDate": "2025-10-26T00:00:00Z",
"endDate": "2025-11-25T23:59:59Z",
"usage": {
"avatars": {
"count": 45,
"creditsSpent": 135,
"byModel": {
"flux": { "count": 30, "credits": 60 },
"imagen3": { "count": 15, "credits": 75 }
}
},
"videos": {
"count": 12,
"creditsSpent": 420,
"totalDuration": 96
},
"audio": {
"count": 8,
"creditsSpent": 85,
"totalDuration": 65
}
},
"totalCreditsSpent": 640,
"averagePerDay": 21.3
}
```
## Subscription Tiers
```bash theme={null}
curl -X GET https://api.percify.io/v1/user/tier \
-H "Authorization: Bearer $PERCIFY_API_KEY"
```
Response:
```json theme={null}
{
"currentTier": "pro",
"tierDetails": {
"name": "Pro",
"monthlyCredits": 500,
"price": 29.99,
"features": [
"500 credits per month",
"Priority processing",
"Advanced models access",
"Batch generation",
"Priority support"
],
"limits": {
"avatarsPerMonth": 1000,
"videosPerMonth": 200,
"voiceClonesTotal": 50,
"concurrentGenerations": 5
}
},
"usage": {
"avatarsThisMonth": 45,
"videosThisMonth": 12,
"voiceClones": 8
},
"billingCycle": {
"start": "2025-11-01T00:00:00Z",
"end": "2025-12-01T00:00:00Z",
"renewalDate": "2025-12-01T00:00:00Z"
}
}
```
## Purchase Credits
```javascript theme={null}
const response = await fetch('https://api.percify.io/v1/user/credits/purchase', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.PERCIFY_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
packId: 'pack_500',
paymentMethod: 'stripe',
returnUrl: 'https://example.com/payment/success'
})
});
const purchase = await response.json();
console.log(`Payment URL: ${purchase.paymentUrl}`);
```
Response:
```json theme={null}
{
"id": "purchase_abc123",
"packId": "pack_500",
"credits": 500,
"price": 49.99,
"currency": "USD",
"paymentUrl": "https://checkout.stripe.com/...",
"status": "pending",
"expiresAt": "2025-11-25T07:00:00Z"
}
```
## Available Credit Packs
| Pack ID | Credits | Price | Bonus | Best For |
| ----------- | ------- | -------- | ----- | ------------- |
| `pack_100` | 100 | \$9.99 | - | Trying out |
| `pack_500` | 500 | \$49.99 | +50 | Regular users |
| `pack_1000` | 1000 | \$89.99 | +150 | Power users |
| `pack_5000` | 5000 | \$399.99 | +1000 | Professionals |
## Update User Profile
```javascript theme={null}
const response = await fetch('https://api.percify.io/v1/user/profile', {
method: 'PATCH',
headers: {
'Authorization': `Bearer ${process.env.PERCIFY_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
displayName: 'Updated Name',
bio: 'AI artist specializing in character design',
website: 'https://newsite.com'
})
});
const profile = await response.json();
```
## Rate Limits by Tier
| Tier | API Requests/min | Concurrent Generations | Priority |
| ---------- | ---------------- | ---------------------- | -------- |
| Free | 10 | 1 | Standard |
| Pro | 60 | 5 | High |
| Enterprise | 300 | 20 | Highest |
## Webhooks
Subscribe to credit and usage events:
```json theme={null}
{
"event": "credits.low_balance",
"data": {
"balance": 25,
"threshold": 50,
"recommendation": "purchase_pack_500"
},
"timestamp": "2025-11-25T06:35:00Z"
}
```
Available events:
* `credits.low_balance` - Balance below threshold
* `credits.purchased` - Credits added
* `tier.upgraded` - Subscription upgraded
* `tier.downgraded` - Subscription downgraded
* `usage.limit_approaching` - Near tier limit
## Error Responses
```json theme={null}
{
"error": {
"code": "payment_failed",
"message": "Payment processing failed. Please check your payment method.",
"details": {
"reason": "insufficient_funds",
"paymentMethod": "card_****1234"
}
}
}
```
Common error codes:
* `invalid_pack_id` - Credit pack doesn't exist
* `payment_failed` - Payment processing error
* `tier_limit_reached` - Monthly limit exceeded
* `invalid_update` - Profile update validation failed
## Best Practices
```javascript theme={null}
// Check balance before expensive operations
async function checkCredits(required) {
const response = await fetch(
'https://api.percify.io/v1/user/credits/balance',
{
headers: {
'Authorization': `Bearer ${process.env.PERCIFY_API_KEY}`
}
}
);
const credits = await response.json();
if (credits.balance < required) {
throw new Error(
`Insufficient credits. Required: ${required}, Available: ${credits.balance}`
);
}
return credits.balance;
}
```
Configure webhooks to:
* Alert when balance is low
* Track usage patterns
* Automate credit purchases
* Monitor tier limits
* Use Flux model for testing (2 credits)
* Keep videos under 5 seconds when possible
* Reuse voice clones (5 credits once)
* Batch similar operations
* Monitor usage statistics regularly
## Next Steps
Understand pricing
Billing and invoices
Optimize performance
# Video Studio API Overview
Source: https://docs.percify.io/api-reference/video-studio/overview
Transform static images into animated videos with AI-powered motion
## Overview
The Video Studio API enables you to convert static avatar images into dynamic video clips with natural motion, facial animations, and optional audio synchronization. Perfect for creating engaging content, animated presentations, and character-driven media.
## Base URL
```
https://api.percify.io/v1
```
## Core Endpoints
| Method | Endpoint | Description |
| ------ | ----------------------------- | -------------------------------- |
| POST | `/videos/from-image` | Generate video from avatar image |
| GET | `/videos/{videoId}` | Get video generation status |
| GET | `/videos` | List your videos |
| POST | `/videos/{videoId}/add-audio` | Add audio track with lip-sync |
| PATCH | `/videos/{videoId}` | Update video metadata |
| DELETE | `/videos/{videoId}` | Delete video |
## Video Object
```json theme={null}
{
"id": "video_xyz789",
"userId": "user_abc123",
"avatarId": "avatar_def456",
"status": "completed",
"videoUrl": "https://cdn.percify.io/videos/video_xyz789.mp4",
"thumbnailUrl": "https://cdn.percify.io/videos/video_xyz789_thumb.jpg",
"durationSeconds": 8,
"resolution": "720p",
"fps": 30,
"fileSize": 3456789,
"format": "mp4",
"studioTier": "basic",
"motionStyle": "moderate",
"creditCost": 48,
"hasAudio": false,
"audioId": null,
"metadata": {
"processingTime": 45.2,
"renderEngine": "video-studio-v3"
},
"createdAt": "2025-11-25T06:15:00Z",
"completedAt": "2025-11-25T06:15:45Z"
}
```
## Pricing
### Basic Video Studio
* **Base:** 30 credits (includes first 5 seconds)
* **Additional:** +6 credits per second after 5s
* **Quality:** 720p, 30fps
* **Max Duration:** 10 seconds
### Reality Lab
* **Base:** 20 credits (includes first 5 seconds)
* **Additional:** +4 credits per second after 5s
* **Quality:** 1080p, 30/60fps
* **Max Duration:** 30 seconds
## Quick Start
```javascript Node.js theme={null}
const response = await fetch('https://api.percify.io/v1/videos/from-image', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.PERCIFY_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
imageId: 'avatar_abc123',
durationSeconds: 5,
studioTier: 'basic',
motionStyle: 'moderate'
})
});
const video = await response.json();
console.log(`Video ID: ${video.id}, Status: ${video.status}`);
```
```python Python theme={null}
import os
import requests
response = requests.post(
'https://api.percify.io/v1/videos/from-image',
headers={
'Authorization': f'Bearer {os.environ["PERCIFY_API_KEY"]}',
'Content-Type': 'application/json'
},
json={
'imageId': 'avatar_abc123',
'durationSeconds': 5,
'studioTier': 'basic',
'motionStyle': 'moderate'
}
)
video = response.json()
print(f"Video ID: {video['id']}, Status: {video['status']}")
```
```bash cURL theme={null}
curl -X POST https://api.percify.io/v1/videos/from-image \
-H "Authorization: Bearer $PERCIFY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"imageId": "avatar_abc123",
"durationSeconds": 5,
"studioTier": "basic",
"motionStyle": "moderate"
}'
```
## Processing Times
| Duration | Tier | Typical Processing |
| -------- | ----------- | ------------------ |
| 3-5s | Basic | 20-35 seconds |
| 6-10s | Basic | 40-75 seconds |
| 3-5s | Reality Lab | 35-60 seconds |
| 10-15s | Reality Lab | 90-150 seconds |
| 15-30s | Reality Lab | 3-5 minutes |
## Motion Styles
| Style | Description | Best For |
| ---------- | --------------------------------------- | ----------------------------------- |
| `subtle` | Gentle breathing, soft blinks | Professional portraits, calm scenes |
| `moderate` | Natural head movements, expressions | Conversations, introductions |
| `dynamic` | Full range motion, dramatic expressions | Action content, music videos |
## Video Formats
**Best compatibility** - Recommended for most uses
* Codec: H.264
* Container: MP4
* Compatibility: All browsers, mobile devices
* File size: Medium
**Smaller file size** - Good for web embedding
* Codec: VP9
* Container: WebM
* Compatibility: Modern browsers
* File size: Small (30% smaller than MP4)
**Highest quality** - For professional editing
* Codec: ProRes
* Container: MOV
* Compatibility: Professional editing software
* File size: Large
* Requires: Reality Lab tier
## Error Responses
```json theme={null}
{
"error": {
"code": "insufficient_credits",
"message": "Not enough credits for 8-second video. Required: 48, Available: 30",
"details": {
"required": 48,
"available": 30,
"calculation": {
"base": 30,
"additional": 18,
"total": 48
}
}
}
}
```
Common error codes:
* `invalid_image` - Avatar image not found or inaccessible
* `invalid_duration` - Duration out of allowed range
* `insufficient_credits` - Not enough credits
* `processing_failed` - Video generation failed
* `avatar_not_completed` - Source avatar still processing
## Polling for Completion
```javascript theme={null}
async function waitForVideo(videoId) {
const maxAttempts = 120; // 10 minutes max
const pollInterval = 5000; // 5 seconds
for (let i = 0; i < maxAttempts; i++) {
const response = await fetch(
`https://api.percify.io/v1/videos/${videoId}`,
{
headers: {
'Authorization': `Bearer ${process.env.PERCIFY_API_KEY}`
}
}
);
const video = await response.json();
if (video.status === 'completed') {
return video;
} else if (video.status === 'failed') {
throw new Error(`Video generation failed: ${video.error}`);
}
await new Promise(resolve => setTimeout(resolve, pollInterval));
}
throw new Error('Video generation timed out');
}
```
## Adding Audio with Lip-Sync
```javascript theme={null}
// Generate video
const video = await client.videos.fromImage({
imageId: 'avatar_abc123',
durationSeconds: 8
});
// Generate audio
const audio = await client.audio.generate({
text: 'Welcome to Percify! Create amazing AI content.',
voiceId: 'voice_default'
});
// Add audio with automatic lip-sync
const syncedVideo = await client.videos.addAudio({
videoId: video.id,
audioId: audio.id,
enableLipSync: true
});
console.log(`Video with audio: ${syncedVideo.videoUrl}`);
```
## Webhooks
Subscribe to video completion events:
```json theme={null}
{
"event": "video.completed",
"data": {
"videoId": "video_xyz789",
"status": "completed",
"videoUrl": "https://cdn.percify.io/videos/video_xyz789.mp4",
"durationSeconds": 8,
"creditCost": 48
},
"timestamp": "2025-11-25T06:15:45Z"
}
```
Available events:
* `video.processing` - Video generation started
* `video.completed` - Video ready for download
* `video.failed` - Generation failed
## Best Practices
* Keep videos under 5 seconds to avoid per-second charges
* Use Basic tier for testing, Reality Lab for production
* Batch similar videos for workflow efficiency
* Reuse successful configurations
* Use high-resolution avatars (1024x1024+)
* Ensure clean, well-lit images
* Center subject in frame
* Avoid heavily cropped faces
* Generate during off-peak hours for faster processing
* Use webhooks instead of polling for long videos
* Download and cache completed videos
* Compress for web delivery if needed
## Rate Limits
| Tier | Concurrent Generations | Daily Limit |
| ---------- | ---------------------- | ----------- |
| Free | 1 | 10 videos |
| Pro | 3 | 100 videos |
| Enterprise | 10 | Unlimited |
## Next Steps
Create video from image
Sync audio with video
Manage your videos
# Getting Started with Percify
Source: https://docs.percify.io/guides/getting-started
Complete beginner's guide to creating your first AI avatar, video, and voice content
## Welcome to Percify!
This guide will walk you through everything you need to know to start creating amazing AI-powered content with Percify. In just 15 minutes, you'll:
* ✅ Set up your account and API access
* ✅ Generate your first AI avatar
* ✅ Convert it to an animated video
* ✅ Add a voice track
* ✅ Understand credits and pricing
* ✅ Explore the community
## Step 1: Create Your Account
Visit [percify.io](https://percify.io) and click "Sign Up"
You can sign up with:
* Email and password
* Google account
* GitHub account
Check your inbox for a verification email and click the confirmation link
New users receive **50 free credits** to explore all features!
This is enough to:
* Generate 10-25 avatars (Flux model)
* Create 1-2 short videos
* Clone 10 voices
* Try all premium features
## Step 2: Get Your API Key
API keys are optional if you only want to use the web dashboard. Skip to Step 3 if you're just getting started with the UI.
For programmatic access:
Click your profile icon → Settings → API Keys
Click "Create New Key" and give it a descriptive name like "My First App"
```bash theme={null}
# Store in environment variable
export PERCIFY_API_KEY="your_api_key_here"
# Or in .env file
echo "PERCIFY_API_KEY=your_api_key_here" >> .env
```
Keep your API key secret! Never commit it to version control or share it publicly.
## Step 3: Generate Your First Avatar
### Via Web Dashboard
From the dashboard, click "Avatar Studio" or the big "Create Avatar" button
Describe what you want to create. Be specific!
**Good examples:**
* "cyberpunk warrior with neon armor, city background, dramatic lighting"
* "friendly robot character, cartoon style, colorful"
* "professional business portrait, confident smile, office background"
**Tips:**
* Include: subject, style, setting, mood, lighting
* Be descriptive but concise (1-2 sentences)
* Use negative prompts to exclude unwanted elements
* **Model:** Start with "Flux" (2 credits, fast)
* **Aspect Ratio:** 1:1 for profile pictures, 16:9 for videos
* **Style Preset:** Try "Professional" or "Cyberpunk"
Click "Generate" and wait 3-5 seconds
Your avatar will appear in the preview. If you like it, great! If not, adjust your prompt and try again.
### Via API
```javascript Node.js theme={null}
const fetch = require('node-fetch');
async function createAvatar() {
const response = await fetch('https://api.percify.io/v1/avatars/generate', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.PERCIFY_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
prompt: 'mystical wizard with glowing staff, fantasy art style',
model: 'flux',
aspectRatio: '1:1'
})
});
const avatar = await response.json();
console.log('Avatar created:', avatar.id);
console.log('Image URL:', avatar.imageUrl);
return avatar;
}
createAvatar();
```
```python Python theme={null}
import os
import requests
def create_avatar():
response = requests.post(
'https://api.percify.io/v1/avatars/generate',
headers={
'Authorization': f'Bearer {os.environ["PERCIFY_API_KEY"]}',
'Content-Type': 'application/json'
},
json={
'prompt': 'mystical wizard with glowing staff, fantasy art style',
'model': 'flux',
'aspectRatio': '1:1'
}
)
avatar = response.json()
print(f"Avatar created: {avatar['id']}")
print(f"Image URL: {avatar['imageUrl']}")
return avatar
create_avatar()
```
## Step 4: Convert to Video
In the dashboard, find the avatar you just created
This opens Video Studio with your avatar pre-loaded
* Start with 3-5 seconds (free with base cost)
* Choose motion style: "Moderate" for natural movement
* Select format: MP4 (best compatibility)
Click "Generate Video"
Processing takes 30-45 seconds. You'll see a progress bar.
**Cost:** 30 credits for 5-second video
Once complete, preview your video and download it!
## Step 5: Add Voice (Optional)
* Record 15-30 seconds of clear speech
* Or use a preset voice
* Upload to Voice Studio
* Wait 30 seconds for cloning (5 credits)
* Write your text (e.g., "Welcome to my channel!")
* Select your cloned voice
* Generate audio (5 credits + 1 per second)
* In Video Studio, add your audio track
* Enable "Auto Lip-Sync"
* Re-render video with audio
## Understanding Credits
Credits are Percify's currency for AI operations:
**2 credits** per generation
Fast, good quality
**5 credits** per generation
Highest quality
**30 credits** base cost
+6 credits per extra second
**5 credits** one-time
Reuse unlimited times
**15 credits** total
5 base + 1 per second
**10-30 credits**
Percify Yourself, Avatar Cast
### Purchase More Credits
When you run low:
1. Go to Settings → Credits
2. Choose a pack:
* 100 credits - \$9.99
* 500 credits - \$49.99 (+50 bonus)
* 1000 credits - \$89.99 (+150 bonus)
3. Pay via Stripe or Razorpay
4. Credits appear instantly
### Pro Tip: Subscription Plans
Monthly plans include credits + perks:
| Plan | Price | Credits/mo | Perks |
| -------------- | ------- | ---------- | ------------------------------------ |
| **Free** | \$0 | 0 | Basic features |
| **Pro** | \$29/mo | 500 | Priority processing, advanced models |
| **Enterprise** | Custom | Custom | Dedicated support, custom limits |
## Next Steps
### Explore More Features
Master prompt engineering and advanced generation
Learn motion styles, camera effects, and optimization
Create perfect voice clones and natural speech
Build apps with Percify's powerful API
### Join the Community
Chat with creators and get help
Get inspired by community creations
Tutorials, tips, and updates
## Common Questions
* Verify your email (+10 credits)
* Complete profile (+5 credits)
* Share your first creation (+10 credits)
* Refer friends (50 credits per signup)
* Avatars: 3-10 seconds
* Videos: 30 seconds to 5 minutes (depends on length)
* Voice cloning: 30-60 seconds
* Audio generation: 2-5 seconds
Yes! All content you create is yours to use commercially. See our [Terms of Service](https://percify.io/terms) for details.
* Adjust your prompt and regenerate
* Try different models
* Use negative prompts to exclude unwanted elements
* Check out the [Prompt Engineering Guide](/guides/prompt-engineering)
* Keys are encrypted at rest
* Use HTTPS only
* Rotate keys regularly
* Never share or commit to version control
## Troubleshooting
| Issue | Solution |
| -------------------- | ------------------------------------------------------ |
| Generation stuck | Wait 30s, refresh page. Contact support if >2 minutes |
| Insufficient credits | Purchase credits or wait for monthly renewal |
| Poor quality results | Use more descriptive prompts, try premium models |
| API errors | Check API key, ensure valid JSON, review error message |
| Payment failed | Verify payment method, check for sufficient funds |
## Need Help?
Comprehensive FAQ and guides
Email our support team
Get help from the community
***
**Ready to create?** Head to the [Dashboard](https://percify.io/dashboard) and start generating amazing AI content!
# Prompt Engineering Guide
Source: https://docs.percify.io/guides/prompt-engineering
Master the art of writing effective prompts for stunning AI avatars
## Introduction
Prompt engineering is the skill of crafting text descriptions that produce the AI-generated images you envision. This guide teaches you proven techniques to get consistent, high-quality results from Percify's Avatar Studio.
## The Anatomy of a Great Prompt
A well-structured prompt typically includes:
```
[Subject] + [Style/Medium] + [Details] + [Setting] + [Lighting] + [Quality Modifiers]
```
### Example Breakdown
**Prompt:** "Elegant elven sorceress, fantasy art style, flowing purple robes with gold trim, mystical forest setting, soft glowing lights, highly detailed, 8k"
* **Subject:** Elegant elven sorceress
* **Style:** Fantasy art style
* **Details:** Flowing purple robes with gold trim
* **Setting:** Mystical forest setting
* **Lighting:** Soft glowing lights
* **Quality:** Highly detailed, 8k
## Essential Prompt Components
### 1. Subject (Required)
The main focus of your image. Be specific about:
* Profession: warrior, mage, scientist, artist
* Species: human, elf, robot, alien
* Age: young, middle-aged, elderly
* Gender: male, female, androgynous
* Face: angular, round, sharp features
* Hair: long flowing, short spiky, braided
* Build: athletic, slender, muscular
* Distinctive traits: scars, tattoos, markings
* Emotion: confident, mysterious, joyful, stern
* Pose: portrait, action pose, sitting, standing
* Gaze: looking at camera, looking away, eyes closed
### 2. Art Style
Choose an aesthetic that matches your vision:
photorealistic, hyperrealistic, photo, portrait photography, studio photo
digital art, digital painting, concept art, artstation trending
illustration, hand-drawn, sketch, watercolor, oil painting
3D render, Unreal Engine, Octane render, CGI, Pixar style
anime style, manga, cel shaded, Studio Ghibli, anime portrait
Art Nouveau, Renaissance, Baroque, Impressionist, Cyberpunk
### 3. Visual Details
Add specifics to guide the AI:
```
✅ Good: "wearing futuristic armor with glowing blue accents"
❌ Vague: "wearing armor"
✅ Good: "long flowing silver hair with braids"
❌ Vague: "long hair"
✅ Good: "intricate golden crown with ruby gems"
❌ Vague: "crown"
```
### 4. Setting & Background
Context matters:
cyberpunk city, neon lights, futuristic metropolis, urban alley, rooftop view, city street, skyscrapers
mystical forest, mountain peak, ocean shore, desert landscape, jungle, meadow, waterfall
royal throne room, laboratory, library, bedroom, workshop, spaceship interior, castle hall
floating islands, alien planet, magical dimension, space station, crystal cavern, ethereal realm
### 5. Lighting
Lighting dramatically affects mood:
| Lighting Type | Description | Best For |
| --------------------- | ---------------------- | -------------------------- |
| **Soft lighting** | Gentle, diffused | Portraits, peaceful scenes |
| **Dramatic lighting** | High contrast, shadows | Action, mystery |
| **Golden hour** | Warm, sunset glow | Romantic, warm scenes |
| **Rim lighting** | Backlight outline | Epic, heroic |
| **Neon lighting** | Colorful, electric | Cyberpunk, modern |
| **Moonlight** | Cool, blue tones | Night, mystical |
| **Studio lighting** | Clean, professional | Headshots, professional |
### 6. Quality Modifiers
Boost output quality:
```
highly detailed, 8k, professional, masterpiece, sharp focus,
intricate details, best quality, award winning, trending on artstation
```
## Advanced Techniques
### Weighting & Emphasis
Emphasize important parts:
```javascript theme={null}
// Mintlify supports emphasis syntax
"(glowing eyes:1.3) mystical sorceress" // Strong emphasis on glowing eyes
"warrior with [leather armor]" // De-emphasize armor
```
### Negative Prompts
Exclude unwanted elements:
```text Good Negative Prompts theme={null}
blurry, low quality, distorted, deformed, ugly, bad anatomy,
extra limbs, mutated hands, poorly drawn face, out of frame,
watermark, text, logo, signature
```
```text Common Issues to Avoid theme={null}
# For faces
asymmetric eyes, distorted face, extra fingers, missing fingers
# For bodies
extra arms, extra legs, bad proportions, disconnected limbs
# For overall quality
pixelated, jpeg artifacts, grainy, noisy, compression artifacts
```
### Style Mixing
Combine multiple art styles:
```
"cyberpunk samurai, blend of traditional Japanese art and futuristic neon aesthetic"
"Victorian era portrait in the style of modern digital art"
"anime character with photorealistic rendering"
```
## Prompt Templates
### Professional Headshots
```
professional headshot of [description], business attire,
confident expression, neutral background, studio lighting,
corporate photography, LinkedIn profile photo, sharp focus,
high quality, professional photographer
```
**Example:**
```
professional headshot of middle-aged woman with short brown hair,
business attire, confident smile, neutral gray background,
studio lighting, corporate photography, sharp focus
```
### Fantasy Characters
```
[character type] [race/species], fantasy art style,
[detailed appearance], [clothing/armor description],
[setting], magical atmosphere, [lighting], highly detailed,
concept art, trending on artstation
```
**Example:**
```
powerful elven mage, fantasy art style, long silver hair,
ethereal blue eyes, flowing robes with arcane symbols,
ancient library filled with glowing books, magical atmosphere,
soft mystical lighting, highly detailed, concept art
```
### Cyberpunk/Sci-Fi
```
[character type], cyberpunk style, [tech features],
neon lights, [city description], futuristic, [lighting],
blade runner aesthetic, high tech, detailed, 4k
```
**Example:**
```
female hacker, cyberpunk style, augmented reality glasses,
neon purple and blue lighting, rainy city street with holographic ads,
futuristic, blade runner aesthetic, highly detailed
```
### Cartoon/Stylized
```
[character description], [cartoon style], colorful,
friendly expression, [setting], vibrant colors,
professional character design, clean lines
```
**Example:**
```
cheerful robot mascot, Pixar animation style, colorful,
big friendly eyes, tech workshop setting, vibrant blues and oranges,
professional character design, clean lines
```
## Model-Specific Tips
### Flux (2 credits - Fast)
* Works best with: Clear, straightforward prompts
* Optimal length: 20-50 words
* Strengths: Speed, consistency, general portraits
* Best for: Testing ideas, iterations, simple concepts
**Example:**
```
portrait of young woman, professional photo, natural lighting, smile
```
### Imagen3 (5 credits - Premium)
* Works best with: Detailed, descriptive prompts
* Optimal length: 30-80 words
* Strengths: Photorealism, complex scenes, fine details
* Best for: Final outputs, professional work, detailed characters
**Example:**
```
portrait of young woman with auburn hair and green eyes,
professional photography, natural window lighting creating soft shadows,
genuine smile, wearing elegant navy blazer, blurred office background,
shot with 85mm lens, shallow depth of field, professional headshot
```
### Reality4 (5 credits - Ultra-Realistic)
* Works best with: Highly specific, technical prompts
* Optimal length: 40-100 words
* Strengths: Photorealism, skin textures, lighting accuracy
* Best for: Commercial work, ultra-realistic renders, product demos
**Example:**
```
ultra-realistic portrait of young woman with auburn hair in loose waves,
striking green eyes with natural eye reflections, fair skin with subtle freckles,
professional studio photography, softbox lighting with subtle rim light,
genuine confident smile showing natural teeth, wearing elegant navy blazer,
perfectly focused on eyes, shot with Canon 5D Mark IV, 85mm f/1.4 lens,
shallow depth of field, background softly blurred, professional retouching,
commercial photography quality
```
## Common Mistakes to Avoid
❌ "a person"
✅ "young female scientist with glasses in a modern laboratory"
❌ "beautiful gorgeous stunning amazing incredible ultra mega super..."
✅ Pick 2-3 quality modifiers maximum
❌ "photorealistic anime cartoon oil painting"
✅ Choose one primary style
Always include basic quality excludes in negative prompt
❌ "warrior, mage, dragon, castle, forest, and a robot"
✅ Focus on one or two main subjects
## Iterative Refinement
Perfect prompts come from iteration:
Begin with a basic prompt describing your core vision
See what the AI produces and note what's missing or wrong
Add specific details for elements that need improvement
Exclude unwanted elements that appeared
Add quality modifiers and lighting details
Use the same seed with prompt variations to compare results
## Prompt Library
Save these proven prompts:
### Corporate Professional
```
professional business portrait of [description], wearing formal attire,
confident posture, neutral gray background, studio lighting with soft shadows,
corporate photography style, shot with 85mm lens, sharp focus on face,
professional retouching, LinkedIn profile quality, 4k resolution
```
### Fantasy Hero
```
epic portrait of [hero type], fantasy art, detailed armor with intricate engravings,
heroic pose, dramatic lighting with rim light, mystical background,
concept art style, trending on artstation, highly detailed, 8k,
cinematic composition, professional digital art
```
### Friendly Character
```
friendly [character type], Pixar animation style, big expressive eyes,
warm smile, colorful and vibrant, simple background with soft gradient,
professional character design, clean vector style, appealing to all ages,
animation ready, high quality render
```
### Mysterious Figure
```
mysterious [character type], dramatic portrait, face partially in shadow,
moody atmosphere, dark background with selective lighting, cinematic,
film noir style, high contrast, professional photography,
shallow depth of field, enigmatic expression
```
## Testing Your Prompts
Use this checklist:
* [ ] Clear subject definition
* [ ] Art style specified
* [ ] Important details included
* [ ] Setting/background described
* [ ] Lighting mentioned
* [ ] Quality modifiers added
* [ ] Negative prompt included
* [ ] No conflicting descriptions
* [ ] Reasonable length (20-100 words)
* [ ] Tested with appropriate model
## Resources
Try your prompts
See prompts from other creators
Share and discuss prompts
Programmatic generation
***
**Ready to craft the perfect prompt?** Open [Avatar Studio](https://percify.io/avatar-studio) and start creating!
# SDK & Integration Guide
Source: https://docs.percify.io/guides/sdk-integration
Integrate Percify into your applications with SDKs and examples
## Overview
Percify provides multiple ways to integrate AI avatar generation into your applications. This guide covers official SDKs, REST API integration, and common use cases.
## Official SDKs
NPM package for Node.js and browser
PyPI package with async support
Direct HTTP API for any language
## JavaScript/Node.js SDK
### Installation
```bash theme={null}
npm install @percify/sdk
# or
yarn add @percify/sdk
```
### Quick Start
```javascript theme={null}
import { Percify } from '@percify/sdk';
const percify = new Percify({
apiKey: process.env.PERCIFY_API_KEY
});
// Generate avatar
const avatar = await percify.avatars.generate({
prompt: 'cyberpunk warrior, neon city background',
model: 'flux'
});
console.log(`Avatar created: ${avatar.imageUrl}`);
```
### Complete Example
```javascript theme={null}
import { Percify } from '@percify/sdk';
const client = new Percify({
apiKey: process.env.PERCIFY_API_KEY,
timeout: 60000, // 60 seconds
retries: 3
});
async function createAvatarWorkflow() {
try {
// 1. Generate avatar
console.log('Generating avatar...');
const avatar = await client.avatars.generate({
prompt: 'mystical forest guardian, glowing eyes, fantasy art',
model: 'imagen3',
aspectRatio: '1:1',
negativePrompt: 'blurry, low quality'
});
// Wait for completion
const completedAvatar = await client.avatars.waitForCompletion(avatar.id);
console.log(`Avatar ready: ${completedAvatar.imageUrl}`);
// 2. Convert to video
console.log('Creating video...');
const video = await client.videos.fromImage({
imageId: avatar.id,
durationSeconds: 5,
studioTier: 'basic',
motionStyle: 'moderate'
});
// Wait for video completion
const completedVideo = await client.videos.waitForCompletion(video.id);
console.log(`Video ready: ${completedVideo.videoUrl}`);
// 3. Clone voice and add audio
console.log('Cloning voice...');
const voice = await client.voices.clone({
audioFile: './voice-sample.mp3',
name: 'My Voice'
});
// Generate speech
const audio = await client.audio.generate({
text: 'Welcome to the mystical forest!',
voiceId: voice.id
});
// Add audio to video
const finalVideo = await client.videos.addAudio({
videoId: video.id,
audioId: audio.id,
enableLipSync: true
});
console.log(`Complete video: ${finalVideo.videoUrl}`);
return {
avatar: completedAvatar,
video: finalVideo
};
} catch (error) {
console.error('Error:', error.message);
throw error;
}
}
createAvatarWorkflow();
```
### Error Handling
```javascript theme={null}
import { Percify, PercifyError, InsufficientCreditsError } from '@percify/sdk';
const client = new Percify({ apiKey: process.env.PERCIFY_API_KEY });
try {
const avatar = await client.avatars.generate({
prompt: 'warrior character',
model: 'imagen3'
});
} catch (error) {
if (error instanceof InsufficientCreditsError) {
console.log('Not enough credits. Please purchase more.');
console.log(`Required: ${error.required}, Available: ${error.available}`);
} else if (error instanceof PercifyError) {
console.log(`API Error: ${error.code} - ${error.message}`);
} else {
console.log('Unexpected error:', error);
}
}
```
### Webhooks Integration
```javascript theme={null}
import express from 'express';
import { Percify } from '@percify/sdk';
const app = express();
app.use(express.json());
const client = new Percify({ apiKey: process.env.PERCIFY_API_KEY });
// Webhook endpoint
app.post('/webhooks/percify', async (req, res) => {
const signature = req.headers['x-percify-signature'];
// Verify webhook signature
if (!client.webhooks.verify(req.body, signature)) {
return res.status(401).send('Invalid signature');
}
const event = req.body;
switch (event.type) {
case 'avatar.completed':
console.log(`Avatar ${event.data.avatarId} completed`);
// Process completed avatar
break;
case 'video.completed':
console.log(`Video ${event.data.videoId} ready`);
// Download or process video
break;
case 'credits.low_balance':
console.log(`Low balance: ${event.data.balance} credits`);
// Send notification to user
break;
}
res.sendStatus(200);
});
app.listen(3000);
```
## Python SDK
### Installation
```bash theme={null}
pip install percify
```
### Quick Start
```python theme={null}
from percify import Percify
import os
client = Percify(api_key=os.environ['PERCIFY_API_KEY'])
# Generate avatar
avatar = client.avatars.generate(
prompt='cyberpunk warrior, neon city background',
model='flux'
)
print(f"Avatar created: {avatar.image_url}")
```
### Complete Example
```python theme={null}
import os
import asyncio
from percify import Percify
from percify.exceptions import InsufficientCreditsError, PercifyError
client = Percify(api_key=os.environ['PERCIFY_API_KEY'])
async def create_avatar_workflow():
try:
# 1. Generate avatar
print('Generating avatar...')
avatar = await client.avatars.generate_async(
prompt='mystical forest guardian, glowing eyes, fantasy art',
model='imagen3',
aspect_ratio='1:1',
negative_prompt='blurry, low quality'
)
# Wait for completion
avatar = await client.avatars.wait_for_completion(avatar.id)
print(f"Avatar ready: {avatar.image_url}")
# 2. Convert to video
print('Creating video...')
video = await client.videos.from_image_async(
image_id=avatar.id,
duration_seconds=5,
studio_tier='basic',
motion_style='moderate'
)
# Wait for video completion
video = await client.videos.wait_for_completion(video.id)
print(f"Video ready: {video.video_url}")
# 3. Clone voice and generate audio
print('Cloning voice...')
with open('voice-sample.mp3', 'rb') as f:
voice = await client.voices.clone_async(
audio=f,
name='My Voice'
)
# Generate speech
audio = await client.audio.generate_async(
text='Welcome to the mystical forest!',
voice_id=voice.id
)
# Add audio to video
final_video = await client.videos.add_audio_async(
video_id=video.id,
audio_id=audio.id,
enable_lip_sync=True
)
print(f"Complete video: {final_video.video_url}")
return {
'avatar': avatar,
'video': final_video
}
except InsufficientCreditsError as e:
print(f'Not enough credits. Required: {e.required}, Available: {e.available}')
except PercifyError as e:
print(f'API Error: {e.code} - {e.message}')
except Exception as e:
print(f'Unexpected error: {e}')
# Run async workflow
asyncio.run(create_avatar_workflow())
```
### Flask Webhook Integration
```python theme={null}
from flask import Flask, request, jsonify
from percify import Percify
import os
app = Flask(__name__)
client = Percify(api_key=os.environ['PERCIFY_API_KEY'])
@app.route('/webhooks/percify', methods=['POST'])
def webhook():
signature = request.headers.get('X-Percify-Signature')
# Verify webhook signature
if not client.webhooks.verify(request.get_data(), signature):
return 'Invalid signature', 401
event = request.get_json()
if event['type'] == 'avatar.completed':
print(f"Avatar {event['data']['avatarId']} completed")
# Process completed avatar
elif event['type'] == 'video.completed':
print(f"Video {event['data']['videoId']} ready")
# Download or process video
elif event['type'] == 'credits.low_balance':
print(f"Low balance: {event['data']['balance']} credits")
# Send notification
return jsonify({'status': 'received'}), 200
if __name__ == '__main__':
app.run(port=3000)
```
## REST API Integration
For languages without an official SDK, use the REST API directly:
### cURL Examples
```bash theme={null}
# Generate avatar
curl -X POST https://api.percify.io/v1/avatars/generate \
-H "Authorization: Bearer $PERCIFY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "cyberpunk warrior",
"model": "flux"
}'
# Check status
curl -X GET https://api.percify.io/v1/avatars/avatar_123 \
-H "Authorization: Bearer $PERCIFY_API_KEY"
# Generate video
curl -X POST https://api.percify.io/v1/videos/from-image \
-H "Authorization: Bearer $PERCIFY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"imageId": "avatar_123",
"durationSeconds": 5
}'
```
### PHP Example
```php theme={null}
$prompt,
'model' => $model
];
$options = [
'http' => [
'header' => [
"Authorization: Bearer $apiKey",
'Content-Type: application/json'
],
'method' => 'POST',
'content' => json_encode($data)
]
];
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
return json_decode($result, true);
}
$apiKey = getenv('PERCIFY_API_KEY');
$avatar = generateAvatar($apiKey, 'mystical wizard, fantasy art');
echo "Avatar ID: " . $avatar['id'] . "\n";
echo "Status: " . $avatar['status'] . "\n";
?>
```
### Ruby Example
```ruby theme={null}
require 'net/http'
require 'json'
require 'uri'
class PercifyClient
def initialize(api_key)
@api_key = api_key
@base_url = 'https://api.percify.io/v1'
end
def generate_avatar(prompt, model: 'flux')
uri = URI("#{@base_url}/avatars/generate")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri.path)
request['Authorization'] = "Bearer #{@api_key}"
request['Content-Type'] = 'application/json'
request.body = {
prompt: prompt,
model: model
}.to_json
response = http.request(request)
JSON.parse(response.body)
end
end
client = PercifyClient.new(ENV['PERCIFY_API_KEY'])
avatar = client.generate_avatar('cyberpunk warrior, neon city')
puts "Avatar ID: #{avatar['id']}"
puts "Status: #{avatar['status']}"
```
## Common Integration Patterns
### Batch Processing
```javascript theme={null}
// Process multiple avatars in parallel
async function batchGenerate(prompts) {
const promises = prompts.map(prompt =>
client.avatars.generate({ prompt, model: 'flux' })
);
const avatars = await Promise.all(promises);
// Wait for all to complete
const completed = await Promise.all(
avatars.map(a => client.avatars.waitForCompletion(a.id))
);
return completed;
}
const prompts = [
'warrior character',
'mage character',
'rogue character'
];
const avatars = await batchGenerate(prompts);
```
### Queue System
```javascript theme={null}
import Queue from 'bull';
const avatarQueue = new Queue('avatar-generation', {
redis: { host: 'localhost', port: 6379 }
});
// Add job
avatarQueue.add({
prompt: 'fantasy character',
userId: 'user_123'
});
// Process job
avatarQueue.process(async (job) => {
const { prompt, userId } = job.data;
const avatar = await client.avatars.generate({ prompt });
const completed = await client.avatars.waitForCompletion(avatar.id);
// Save to database or notify user
await saveAvatarForUser(userId, completed);
return completed;
});
```
### Retry Logic
```javascript theme={null}
async function generateWithRetry(prompt, maxRetries = 3) {
let lastError;
for (let i = 0; i < maxRetries; i++) {
try {
const avatar = await client.avatars.generate({ prompt });
return await client.avatars.waitForCompletion(avatar.id);
} catch (error) {
lastError = error;
if (error instanceof InsufficientCreditsError) {
throw error; // Don't retry
}
// Wait before retry (exponential backoff)
await new Promise(resolve =>
setTimeout(resolve, Math.pow(2, i) * 1000)
);
}
}
throw lastError;
}
```
## Best Practices
* Store in environment variables
* Never commit to version control
* Use different keys for dev/prod
* Rotate regularly
* Implement key scoping if available
```javascript theme={null}
const client = new Percify({
apiKey: process.env.PERCIFY_API_KEY,
timeout: 60000, // 60 seconds
retries: 3,
retryDelay: 1000
});
```
Instead of polling:
```javascript theme={null}
// ❌ Polling
while (status !== 'completed') {
await sleep(5000);
status = await checkStatus();
}
// ✅ Webhooks
await client.videos.generate({ imageId, webhookUrl });
// Webhook notifies when complete
```
```javascript theme={null}
// Check credits before expensive operations
const credits = await client.user.getCredits();
if (credits.balance < 50) {
console.warn('Low credits!');
}
// Track usage
const usage = await client.user.getUsage({ period: '30d' });
console.log(`Credits spent: ${usage.totalCreditsSpent}`);
```
```javascript theme={null}
function validatePrompt(prompt) {
if (!prompt || prompt.length < 3) {
throw new Error('Prompt too short');
}
if (prompt.length > 500) {
throw new Error('Prompt too long');
}
// Check for prohibited content
// ...
return true;
}
```
## Deployment Considerations
### Environment Variables
```.env theme={null}
PERCIFY_API_KEY=your_api_key_here
PERCIFY_WEBHOOK_SECRET=your_webhook_secret
PERCIFY_TIMEOUT=60000
PERCIFY_MAX_RETRIES=3
```
### Rate Limiting
```javascript theme={null}
import rateLimit from 'express-rate-limit';
const limiter = rateLimit({
windowMs: 60 * 1000, // 1 minute
max: 10 // 10 requests per minute
});
app.use('/api/generate', limiter);
```
### Caching
```javascript theme={null}
import NodeCache from 'node-cache';
const cache = new NodeCache({ stdTTL: 3600 }); // 1 hour
async function getCachedAvatar(avatarId) {
const cached = cache.get(avatarId);
if (cached) return cached;
const avatar = await client.avatars.get(avatarId);
cache.set(avatarId, avatar);
return avatar;
}
```
## Next Steps
Complete API documentation
Code examples repository
Get integration help
# Webhooks
Source: https://docs.percify.io/guides/webhooks
Receive real-time notifications for Percify events
## Overview
Webhooks allow you to receive real-time HTTP notifications when events occur in your Percify account. Instead of polling the API for status updates, webhooks push updates to your server automatically.
## Benefits
Get notified instantly when events occur
No need to poll for status updates
Save credits and reduce latency
## Setting Up Webhooks
### 1. Create an Endpoint
Create an HTTPS endpoint on your server to receive webhook events:
```javascript Node.js/Express theme={null}
const express = require('express');
const app = express();
app.use(express.json());
app.post('/webhooks/percify', async (req, res) => {
const event = req.body;
console.log('Received event:', event.type);
// Process event
switch (event.type) {
case 'avatar.completed':
await handleAvatarCompleted(event.data);
break;
case 'video.completed':
await handleVideoCompleted(event.data);
break;
// Handle other events...
}
// Acknowledge receipt
res.sendStatus(200);
});
app.listen(3000);
```
```python Python/Flask theme={null}
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/webhooks/percify', methods=['POST'])
def webhook():
event = request.get_json()
print(f"Received event: {event['type']}")
# Process event
if event['type'] == 'avatar.completed':
handle_avatar_completed(event['data'])
elif event['type'] == 'video.completed':
handle_video_completed(event['data'])
# Handle other events...
# Acknowledge receipt
return jsonify({'status': 'received'}), 200
if __name__ == '__main__':
app.run(port=3000)
```
```php PHP theme={null}
'received']);
?>
```
### 2. Register Webhook URL
Register your endpoint in the Percify dashboard:
Go to Dashboard → Settings → Webhooks
Click "Add Endpoint" and enter your webhook URL
**Requirements:**
* Must be HTTPS (required for production)
* Must respond within 10 seconds
* Should return 2xx status code
Choose which events to receive:
* All events (recommended for development)
* Specific event types only
Save your webhook and click "Send Test Event" to verify
### 3. Verify Webhook Signatures
Always verify webhook signatures to ensure requests are from Percify:
```javascript Node.js theme={null}
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
app.post('/webhooks/percify', (req, res) => {
const signature = req.headers['x-percify-signature'];
const secret = process.env.PERCIFY_WEBHOOK_SECRET;
if (!verifyWebhook(JSON.stringify(req.body), signature, secret)) {
return res.status(401).send('Invalid signature');
}
// Process event...
res.sendStatus(200);
});
```
```python Python theme={null}
import hmac
import hashlib
def verify_webhook(payload: bytes, signature: str, secret: str) -> bool:
expected_signature = hmac.new(
secret.encode(),
payload,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected_signature)
@app.route('/webhooks/percify', methods=['POST'])
def webhook():
signature = request.headers.get('X-Percify-Signature')
secret = os.environ['PERCIFY_WEBHOOK_SECRET']
if not verify_webhook(request.get_data(), signature, secret):
return 'Invalid signature', 401
# Process event...
return jsonify({'status': 'received'}), 200
```
## Event Types
### Avatar Events
#### `avatar.completed`
Fired when avatar generation completes successfully.
```json theme={null}
{
"type": "avatar.completed",
"id": "evt_abc123",
"created": "2025-11-25T06:40:00Z",
"data": {
"avatarId": "avatar_xyz789",
"userId": "user_abc123",
"status": "completed",
"imageUrl": "https://cdn.percify.io/avatars/avatar_xyz789.png",
"thumbnailUrl": "https://cdn.percify.io/avatars/avatar_xyz789_thumb.png",
"creditCost": 5,
"model": "imagen3",
"prompt": "mystical forest guardian"
}
}
```
#### `avatar.failed`
Fired when avatar generation fails.
```json theme={null}
{
"type": "avatar.failed",
"id": "evt_def456",
"created": "2025-11-25T06:41:00Z",
"data": {
"avatarId": "avatar_xyz789",
"userId": "user_abc123",
"status": "failed",
"error": {
"code": "content_policy_violation",
"message": "Prompt violates content policy"
}
}
}
```
#### `avatar.published`
Fired when an avatar is published to the community feed.
```json theme={null}
{
"type": "avatar.published",
"id": "evt_ghi789",
"created": "2025-11-25T06:42:00Z",
"data": {
"avatarId": "avatar_xyz789",
"userId": "user_abc123",
"visibility": "public",
"publishedAt": "2025-11-25T06:42:00Z"
}
}
```
### Video Events
#### `video.completed`
Fired when video generation completes.
```json theme={null}
{
"type": "video.completed",
"id": "evt_jkl012",
"created": "2025-11-25T06:45:00Z",
"data": {
"videoId": "video_abc123",
"userId": "user_xyz789",
"avatarId": "avatar_def456",
"status": "completed",
"videoUrl": "https://cdn.percify.io/videos/video_abc123.mp4",
"thumbnailUrl": "https://cdn.percify.io/videos/video_abc123_thumb.jpg",
"durationSeconds": 8,
"creditCost": 48,
"resolution": "720p"
}
}
```
#### `video.failed`
Fired when video generation fails.
```json theme={null}
{
"type": "video.failed",
"id": "evt_mno345",
"created": "2025-11-25T06:46:00Z",
"data": {
"videoId": "video_abc123",
"userId": "user_xyz789",
"status": "failed",
"error": {
"code": "processing_error",
"message": "Video generation failed due to server error"
}
}
}
```
### Audio Events
#### `audio.completed`
Fired when audio generation completes.
```json theme={null}
{
"type": "audio.completed",
"id": "evt_pqr678",
"created": "2025-11-25T06:50:00Z",
"data": {
"audioId": "audio_xyz123",
"userId": "user_abc456",
"voiceId": "voice_def789",
"status": "completed",
"audioUrl": "https://cdn.percify.io/audio/audio_xyz123.mp3",
"durationSeconds": 5.2,
"creditCost": 10
}
}
```
#### `voice.cloned`
Fired when voice cloning completes.
```json theme={null}
{
"type": "voice.cloned",
"id": "evt_stu901",
"created": "2025-11-25T06:52:00Z",
"data": {
"voiceId": "voice_abc123",
"userId": "user_xyz789",
"name": "My Custom Voice",
"language": "en-US",
"status": "completed",
"creditCost": 5
}
}
```
### Credit Events
#### `credits.low_balance`
Fired when credit balance drops below threshold.
```json theme={null}
{
"type": "credits.low_balance",
"id": "evt_vwx234",
"created": "2025-11-25T06:55:00Z",
"data": {
"userId": "user_abc123",
"balance": 25,
"threshold": 50,
"recommendation": "purchase_pack_500"
}
}
```
#### `credits.purchased`
Fired when credits are purchased.
```json theme={null}
{
"type": "credits.purchased",
"id": "evt_yz567",
"created": "2025-11-25T06:58:00Z",
"data": {
"userId": "user_abc123",
"purchaseId": "purchase_xyz789",
"amount": 500,
"bonusAmount": 50,
"newBalance": 575,
"price": 49.99,
"currency": "USD"
}
}
```
### User Events
#### `tier.upgraded`
Fired when user upgrades subscription tier.
```json theme={null}
{
"type": "tier.upgraded",
"id": "evt_abc890",
"created": "2025-11-25T07:00:00Z",
"data": {
"userId": "user_abc123",
"previousTier": "free",
"newTier": "pro",
"effectiveDate": "2025-11-25T07:00:00Z"
}
}
```
## Implementing Event Handlers
### Complete Example
```javascript theme={null}
const express = require('express');
const { verifyWebhook } = require('./utils/webhook');
const { processAvatar, processVideo, notifyUser } = require('./handlers');
const app = express();
app.use(express.json());
const eventHandlers = {
'avatar.completed': async (data) => {
console.log(`Avatar ${data.avatarId} completed`);
// Save to database
await db.avatars.update(data.avatarId, {
status: 'completed',
imageUrl: data.imageUrl
});
// Notify user
await notifyUser(data.userId, {
type: 'avatar_ready',
avatarId: data.avatarId
});
// Start video generation if configured
if (shouldGenerateVideo(data.userId)) {
await startVideoGeneration(data.avatarId);
}
},
'video.completed': async (data) => {
console.log(`Video ${data.videoId} completed`);
// Update database
await db.videos.update(data.videoId, {
status: 'completed',
videoUrl: data.videoUrl
});
// Send email notification
await sendEmail(data.userId, {
subject: 'Your video is ready!',
videoUrl: data.videoUrl
});
},
'credits.low_balance': async (data) => {
console.log(`User ${data.userId} has low credits: ${data.balance}`);
// Send push notification
await sendPushNotification(data.userId, {
title: 'Running low on credits',
body: `You have ${data.balance} credits remaining.`,
action: 'purchase_credits'
});
},
'avatar.failed': async (data) => {
console.error(`Avatar ${data.avatarId} failed:`, data.error);
// Log error
await logError(data.avatarId, data.error);
// Refund credits if appropriate
if (shouldRefund(data.error.code)) {
await refundCredits(data.userId, data.creditCost);
}
// Notify user
await notifyUser(data.userId, {
type: 'avatar_failed',
avatarId: data.avatarId,
error: data.error.message
});
}
};
app.post('/webhooks/percify', async (req, res) => {
const signature = req.headers['x-percify-signature'];
const secret = process.env.PERCIFY_WEBHOOK_SECRET;
// Verify signature
if (!verifyWebhook(JSON.stringify(req.body), signature, secret)) {
return res.status(401).send('Invalid signature');
}
const event = req.body;
// Handle event
const handler = eventHandlers[event.type];
if (handler) {
try {
await handler(event.data);
} catch (error) {
console.error(`Error handling ${event.type}:`, error);
// Still return 200 to avoid retries for application errors
}
} else {
console.log(`Unhandled event type: ${event.type}`);
}
res.sendStatus(200);
});
app.listen(3000);
```
## Best Practices
Never process webhooks without signature verification. This prevents replay attacks and ensures authenticity.
```javascript theme={null}
if (!verifySignature(payload, signature, secret)) {
return res.status(401).send('Invalid signature');
}
```
Acknowledge receipt within 10 seconds. Process heavy tasks asynchronously.
```javascript theme={null}
app.post('/webhooks/percify', async (req, res) => {
// Acknowledge immediately
res.sendStatus(200);
// Process asynchronously
processWebhookAsync(req.body).catch(console.error);
});
```
Percify retries failed webhooks with exponential backoff. Make your handlers idempotent.
```javascript theme={null}
async function handleAvatarCompleted(data) {
// Check if already processed
const existing = await db.find(data.avatarId);
if (existing?.processed) {
return; // Skip duplicate
}
// Process and mark as complete
await processAvatar(data);
await db.markProcessed(data.avatarId);
}
```
```javascript theme={null}
const queue = new Queue('webhooks');
app.post('/webhooks/percify', async (req, res) => {
// Add to queue
await queue.add(req.body);
// Respond immediately
res.sendStatus(200);
});
// Process queue asynchronously
queue.process(async (job) => {
await processEvent(job.data);
});
```
Keep detailed logs for debugging:
```javascript theme={null}
await logWebhook({
eventId: event.id,
eventType: event.type,
receivedAt: new Date(),
payload: event.data,
processed: true
});
```
## Testing Webhooks
### Local Development with ngrok
```bash theme={null}
# Install ngrok
npm install -g ngrok
# Start your server
node server.js
# Create tunnel in another terminal
ngrok http 3000
# Use the HTTPS URL in Percify dashboard
# https://abc123.ngrok.io/webhooks/percify
```
### Test Events
Send test events from the dashboard or via CLI:
```bash theme={null}
curl -X POST https://your-domain.com/webhooks/percify \
-H "Content-Type: application/json" \
-H "X-Percify-Signature: test_signature" \
-d '{
"type": "avatar.completed",
"id": "evt_test123",
"created": "2025-11-25T07:00:00Z",
"data": {
"avatarId": "avatar_test",
"status": "completed"
}
}'
```
## Troubleshooting
| Issue | Cause | Solution |
| --------------------- | ---------------------------------- | --------------------------------- |
| Webhooks not received | URL not HTTPS | Use HTTPS for production |
| 401 Invalid signature | Wrong secret or verification logic | Check webhook secret in dashboard |
| Timeout errors | Handler takes too long | Respond within 10s, process async |
| Duplicate events | Retry logic | Implement idempotent handlers |
| Events out of order | Network delays | Don't rely on event order |
## Security Checklist
* [ ] Always verify webhook signatures
* [ ] Use HTTPS endpoints only
* [ ] Respond within 10 seconds
* [ ] Store webhook secrets securely
* [ ] Implement idempotent handlers
* [ ] Log all webhook events
* [ ] Monitor for suspicious activity
* [ ] Rate limit webhook endpoint
* [ ] Validate event data structure
* [ ] Handle errors gracefully
## Next Steps
Explore all API endpoints
Use official SDKs
Get webhook setup help
# Percify Overview
Source: https://docs.percify.io/index
What Percify is, what you can build, and where to go next
## What is Percify?
Percify is a creative AI platform for generating and managing personalized avatars, transforming images into short form videos, cloning voices, and publishing safe, performant user‑generated media at scale.
Create & evolve AI avatars
Turn stills into dynamic clips
Generate natural speech
Predictable usage-based pricing
Integrate programmatically
Optimized & scalable
New here? Start with the [Quickstart](/quickstart) or jump straight to [Avatar Studio](/percify/avatar-studio).
## Core User Journey
Create your Percify account and obtain your API key from the dashboard
Purchase credits or receive starter credits with your plan
Use Avatar Studio to create stunning AI-generated portraits
Convert your avatar to a dynamic short video clip
Clone your voice or use AI voices for narration
Publish to the feed or integrate via API
## Why Credits?
Credits provide transparent, tier‑agnostic pricing and enable advanced features like per‑second video scaling, fair voice generation metering, and future tier overrides.
See the full breakdown in [Credits & Pricing](/percify/credits).
## Reliability & Safety
Percify implements a ban system, content visibility controls, and rate limiting to keep the platform healthy. Learn more in [Security & Trust](/percify/security).
## Architecture at a Glance
Stack, flows, data stores
Endpoints & schemas
## Next Steps
Get started in 5 minutes
Create amazing avatars
Common questions
## Support
Need help? Reach out via [support@percify.io](mailto:support@percify.io) or check our [FAQ](/percify/faq).
# API Authentication
Source: https://docs.percify.io/percify/api-auth
Using API keys securely with Percify endpoints
## Overview
Percify authenticates programmatic access via static API keys scoped to a user account. Keys must be kept server-side—never expose them in client bundles.
## Obtaining a Key
1. Visit Dashboard → Settings → API Keys
2. Generate new key (label for internal tracking)
3. Copy once; regenerate if leaked
## Request Format
Include header:
```
Authorization: Bearer
```
Content-Type header required for JSON POST bodies.
## Example
```bash theme={null}
curl -X POST https://api.percify.io/v1/images/generate \
-H "Authorization: Bearer $PERCIFY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"prompt":"vibrant portrait, rim light"}'
```
## Verifying Identity
Server resolves the user from key → attaches userId in request context → ban & credit checks applied.
## Rotation Strategy
| Scenario | Action |
| ------------------ | ------------------------------- |
| Routine security | Rotate quarterly |
| Suspected leak | Revoke + regenerate immediately |
| Ownership transfer | Delete old keys before handoff |
## Handling Failures
| Status | Meaning | Fix |
| ------ | ------------------- | --------------------------- |
| 401 | Missing/invalid key | Provide valid header |
| 403 | Banned user | Appeal or resolve violation |
| 429 | Rate limit | Backoff + retry |
## Storing Keys
| Environment | Method |
| ----------- | ------------------------------- |
| Local Dev | `.env.local` (never commit) |
| CI/CD | Platform secret manager |
| Production | Vault / encrypted secrets store |
## Do Not
* Embed in client-side JavaScript
* Log full key values
* Share keys across unrelated services
## Related Pages
* \[/quickstart]
* \[/percify/security]
* \[/api-reference/introduction]
***
Next: browse endpoints in \[/api-reference/introduction].
# Architecture
Source: https://docs.percify.io/percify/architecture
High-level system design, data flows, and core services
## Overview
Percify combines a Next.js application layer, specialized generation workers, and a PostgreSQL database for persistent entities (users, avatars, media metadata, credits). Object storage (GCS/S3 compatible) is used for generated media assets. A unified credit system mediates feature access and billing.
## Core Components
| Component | Purpose | Tech |
| ------------------ | ----------------------------------------- | ------------------------------------- |
| Web App | User dashboard & Studio UX | Next.js (App Router), React, Tailwind |
| Admin App | Moderation, system ops | Next.js + role gating |
| Docs App | Public product docs | Mintlify MDX site |
| API Routes | Feature endpoints (image/video/audio) | Next.js Route Handlers |
| Generation Workers | Offloaded heavy model inference | Provider APIs / Background queues |
| PostgreSQL | Relational data (users, avatars, credits) | Managed Postgres |
| Object Storage | Media asset persistence | GCS / CDN |
| Credit Engine | Centralized cost logic | `credit-costs.ts` |
| Ban System | Safety enforcement | `ban-check.ts`, DB columns |
## Data Flow: Image → Video → Voice
1. User submits image prompt (POST /images/generate)
2. Credits pre-authorized; job enqueued
3. Worker/model returns image asset → metadata saved
4. User requests video (POST /videos/from-image) referencing imageId
5. Duration cost calculated (base + perSecond)
6. Optional voice generation; audio asset linked
7. Composite published (visibility rules applied)
## Credit Calculation
Central file (`src/lib/credit-costs.ts`) exports:
* `getFeatureCost(feature)` simple lookups
* `calculateVideoCost(durationSeconds, type)` base + incremental
* `calculateAudioCost(durationSeconds)` duration metering
Future expansion: tier overrides in `TIER_COSTS` map.
## Safety & Moderation
* Ban columns on `user` table: `banned`, `banned_at`, `banned_reason`
* Middleware/utility `requireNotBanned(userId)` used across write endpoints
* Private vs public visibility flags for avatars/videos
* Rate limiting (not shown here) recommended at API gateway level
## Performance Patterns
* Consolidated COUNT aggregation using filtered UNION strategy for dashboard metrics
* Targeted indexes for feed/explore & dashboard queries (see Performance page)
* Caching: CDN + stale-while-revalidate for feed endpoints
## Extensibility
Add new generation feature:
1. Define costs in `FeatureCosts`
2. Implement route handler with pre-check (auth + ban + credits)
3. Store metadata row, emit event for async post-processing
4. Expose retrieval endpoint & add to docs navigation
## High-Level Sequence (Pseudo)
```mermaid theme={null}
graph TD;
A[Request: Generate Image] --> B[Auth + Ban Check];
B --> C[Credit Precheck];
C --> D[Enqueue Job];
D --> E[Worker Generates Asset];
E --> F[Persist Metadata + Credit Debit];
F --> G[User Refines / Publishes];
G --> H[Video Generation];
H --> I[Voice Generation];
I --> J[Public Delivery via CDN];
```
## Environment Separation
| Env | Purpose | Notes |
| ----------- | ------------------- | ----------------------------- |
| Development | Local iteration | Test credits & mock providers |
| Staging | Pre-prod validation | Lower model concurrency |
| Production | Live users | Full observability + alerts |
## Observability (Recommended)
* Structured logs around generation timings & credit debits
* Slow query detection with threshold logging (>500ms)
* Endpoint latency percentiles to tune caching
## Future Improvements
* Tier-based dynamic pricing
* Materialized views for extreme high-volume dashboards
* Event-driven webhook emission on asset lifecycle
* Quota vs credit hybrid for enterprise plans
***
For detailed performance tactics see \[/percify/performance].
# Avatar Studio
Source: https://docs.percify.io/percify/avatar-studio
Create, refine, and publish AI-generated avatars with Percify's Avatar Studio
## Overview
Avatar Studio is Percify's flagship feature for creating personalized AI avatars. Generate stunning portraits, characters, and artistic representations using state-of-the-art AI models, then refine and publish them to your profile or integrate them into your applications.
Generate avatars in seconds with simple text prompts
Choose from multiple AI models and artistic styles
Refine results with prompt engineering and variations
Publish to public feed or keep private for personal use
## Generation Models
Percify offers multiple AI models optimized for different use cases:
### Flux (Standard)
* **Cost:** 2 credits per generation
* **Speed:** \~3-5 seconds
* **Best for:** Quick iterations, concept exploration, general portraits
* **Quality:** High quality with good prompt adherence
### Imagen3 (Premium)
* **Cost:** 5 credits per generation
* **Speed:** \~5-8 seconds
* **Best for:** Professional portraits, detailed characters
* **Quality:** Exceptional detail and photorealism
### Reality4 (Premium)
* **Cost:** 5 credits per generation
* **Speed:** \~6-10 seconds
* **Best for:** Ultra-realistic renders, commercial use
* **Quality:** Industry-leading photorealism
## Creating Your First Avatar
From the dashboard, click "Avatar Studio" or use the quick-create button
Describe your desired avatar. Be specific about:
* Physical features and appearance
* Style (realistic, artistic, anime, etc.)
* Mood and expression
* Background and setting
* Lighting conditions
* Choose AI model (Flux, Imagen3, Reality4)
* Set aspect ratio (1:1, 16:9, 9:16)
* Adjust guidance scale (7-15 recommended)
* Set seed for reproducibility (optional)
Click "Generate" and wait 3-10 seconds depending on model
## Prompt Engineering Tips
Use this formula for best results:
```
[Subject] [Style] [Details] [Setting] [Lighting]
```
Example: "Young astronaut, cinematic portrait, futuristic suit with glowing accents, nebula background, soft rim lighting"
Effective descriptors:
* **Quality:** high resolution, detailed, sharp focus, professional
* **Style:** photorealistic, oil painting, anime style, cyberpunk, fantasy
* **Lighting:** dramatic lighting, golden hour, neon glow, studio lighting
* **Mood:** serene, confident, mysterious, joyful
Exclude unwanted elements:
```
Negative: blurry, low quality, distorted, extra limbs, text, watermark
```
1. Start with a simple, clear prompt
2. Generate and evaluate results
3. Add specific details to refine
4. Adjust model or settings if needed
5. Keep successful prompts for reuse
## Advanced Features
### Percify Yourself
Transform your own photos into AI avatars that maintain your likeness while applying different styles.
* **Cost:** 10 credits per generation
* **Requirements:** Clear front-facing photo, good lighting, neutral background
* **Process:** Upload photo → Select style → Generate → Refine
```bash theme={null}
curl -X POST https://api.percify.io/v1/avatars/percify-yourself \
-H "Authorization: Bearer $PERCIFY_API_KEY" \
-H "Content-Type: multipart/form-data" \
-F "image=@portrait.jpg" \
-F "style=cyberpunk" \
-F "prompt=futuristic warrior, neon lights"
```
### Avatar Cast
Create multi-character scenes with consistent styling across characters.
* **Cost:** 30 credits per generation
* **Use cases:** Team portraits, group scenes, character lineups
* **Features:** Automatic composition, consistent lighting, style coherence
### Style Presets
Quick-start templates for common avatar types:
LinkedIn-ready business portraits
Game character designs and avatars
D\&D characters, mythical beings
Anime and manga style characters
Futuristic, neon-lit sci-fi
Classical art style portraits
## Publishing & Visibility
### Visibility Options
* **Public:** Appears in explore feed, discoverable by all users
* **Unlisted:** Accessible via direct link only
* **Private:** Only visible to you, usable in your projects
### Publishing Process
```typescript theme={null}
const response = await fetch('https://api.percify.io/v1/avatars/publish', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.PERCIFY_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
avatarId: 'avatar_123',
visibility: 'public',
tags: ['cyberpunk', 'portrait', 'character-design'],
description: 'Futuristic explorer character concept'
})
});
```
### Metadata & Tagging
Organize and discover avatars with:
* Custom tags (up to 10 per avatar)
* Descriptions (up to 500 characters)
* Collections (group related avatars)
* Favorites (bookmark for quick access)
## Studio Interface
### Key Controls
| Control | Function |
| --------------- | --------------------------------------- |
| Prompt Box | Enter/edit generation prompt |
| Model Selector | Choose AI model (Flux/Imagen3/Reality4) |
| Aspect Ratio | Set output dimensions |
| Guidance Scale | Control prompt adherence (7-15) |
| Seed | Fix randomness for reproducibility |
| Batch Size | Generate multiple variations (1-4) |
| Negative Prompt | Exclude unwanted elements |
### Generation History
All your generations are saved and accessible:
* View thumbnails in timeline
* Compare variations side-by-side
* Restore previous prompts
* Track credit usage per generation
## Best Practices
**Optimize Credit Usage:** Start with Flux (2 credits) for exploration, switch to premium models when you've refined your prompt.
**Content Policy:** Avatars must comply with Percify's content guidelines. Prohibited content includes violence, hate speech, explicit content, and impersonation of real individuals without consent.
**Performance Tips:**
* Generate during off-peak hours for faster processing
* Use batch generation sparingly (costs multiply)
* Save successful prompts as templates
* Reuse seeds for consistent character designs
## API Integration
### Generate Avatar Image
```javascript theme={null}
// Node.js/JavaScript
const percify = require('@percify/sdk');
const client = new percify.Percify({
apiKey: process.env.PERCIFY_API_KEY
});
const avatar = await client.avatars.generate({
prompt: 'ethereal forest guardian, glowing eyes, mystical atmosphere',
model: 'imagen3',
aspectRatio: '1:1',
guidanceScale: 10,
negativePrompt: 'blurry, low quality'
});
console.log(`Avatar ID: ${avatar.id}, Status: ${avatar.status}`);
```
```python theme={null}
# Python
from percify import Percify
client = Percify(api_key=os.environ['PERCIFY_API_KEY'])
avatar = client.avatars.generate(
prompt='ethereal forest guardian, glowing eyes, mystical atmosphere',
model='imagen3',
aspect_ratio='1:1',
guidance_scale=10,
negative_prompt='blurry, low quality'
)
print(f"Avatar ID: {avatar.id}, Status: {avatar.status}")
```
### Check Generation Status
```bash theme={null}
curl -X GET https://api.percify.io/v1/avatars/avatar_123 \
-H "Authorization: Bearer $PERCIFY_API_KEY"
```
Response:
```json theme={null}
{
"id": "avatar_123",
"status": "completed",
"imageUrl": "https://cdn.percify.io/avatars/avatar_123.png",
"thumbnailUrl": "https://cdn.percify.io/avatars/avatar_123_thumb.png",
"prompt": "ethereal forest guardian...",
"model": "imagen3",
"creditCost": 5,
"createdAt": "2025-11-25T05:30:00Z",
"completedAt": "2025-11-25T05:30:08Z"
}
```
## Troubleshooting
| Issue | Cause | Solution |
| -------------------------------- | ---------------------------- | -------------------------------------------------------------- |
| Generation stuck in "processing" | Server queue or timeout | Wait 30s, check status endpoint, contact support if >2 minutes |
| Poor quality results | Weak prompt or low guidance | Strengthen prompt details, increase guidance scale to 12-15 |
| Unexpected elements | Model interpretation | Add negative prompts, be more specific in main prompt |
| Insufficient credits | Balance below model cost | Purchase credits or switch to lower-cost model |
| 429 Rate limit | Too many concurrent requests | Reduce request frequency, implement exponential backoff |
## Next Steps
Animate your avatars
Add voice to characters
Understand pricing
## Support
Need help with Avatar Studio? Check the [FAQ](/percify/faq) or reach out to [support@percify.io](mailto:support@percify.io).
# Credits System
Source: https://docs.percify.io/percify/credits
Unified pricing logic, feature costs, and metering rationale
## Overview
Percify uses a unified credit model to keep pricing transparent and enable future tier overrides without rewriting feature logic. All generation actions debit credits atomically after success.
## Feature Costs
| Feature | Base | Increment | Notes |
| ---------------------------------- | ---- | ---------- | ------------------------- |
| Image Standard (Flux) | 2 | — | Per output |
| Image Premium (Imagen3 / Reality4) | 5 | — | Per output |
| Percify Yourself | 10 | — | Photo → avatar |
| Avatar Cast | 30 | — | Multi-character scene |
| Voice Cloning | 5 | — | One-time profile creation |
| Audio Generation | 5 | +1/sec | Duration based |
| Video Studio | 30 | +6/sec >5s | 5s base window |
| Reality Lab | 20 | +4/sec >5s | Cinematic motion |
## Centralized Logic (`credit-costs.ts`)
Exports:
* `DEFAULT_COSTS` – baseline values
* `TIER_COSTS` – placeholder map for future tier overrides
* `getFeatureCost(feature)` – simple lookup
* `calculateVideoCost(duration, feature)` – base + perSecond dynamic
* `calculateAudioCost(duration)` – base + perSecond
## Example Usage
```typescript theme={null}
import { calculateVideoCost, getFeatureCost } from '@/lib/credit-costs';
const imageCost = getFeatureCost('imageStandard'); // 2
const videoCost = calculateVideoCost(12, 'videoStudio'); // 30 + 7*6 = 72
```
## Debit Flow
1. User initiates generation
2. System validates sufficient balance
3. Job runs (async or inline)
4. On success → debit transaction committed
5. On failure → no debit (idempotent)
## UI Display
Use `getAllCosts()` to present current pricing table; dynamic adjustments possible once tier overrides implemented.
## Future Tier Pricing (Planned)
| Tier | Override Strategy |
| --------- | --------------------------------- |
| free | Defaults |
| starter | Potential volume discounts |
| creator | Premium model cost reduction |
| scale | Lower per-second video increments |
| unlimited | Custom negotiated bundle |
## Rationale
| Goal | Approach |
| --------------- | ----------------------------------------- |
| Consistency | Single source of truth file |
| Flexibility | Tier override map ready |
| Transparency | Deterministic cost formulas |
| Maintainability | Eliminates 19+ hardcoded scattered values |
## Troubleshooting
| Problem | Cause | Resolution |
| --------------------------------- | ----------------------------- | ------------------------------------ |
| Unexpected high debit | Long durations or cast scenes | Check cost formula before confirming |
| Mismatch UI vs API cost | Stale client cache | Refresh pricing via API or rebuild |
| Insufficient balance mid workflow | Multiple queued jobs | Reserve credits (planned feature) |
## Related Pages
* \[/percify/payments]
* \[/percify/image-to-video]
* \[/percify/voice-cloning]
***
Continue to payment flows at \[/percify/payments].
# FAQ & Troubleshooting
Source: https://docs.percify.io/percify/faq
Answers to common questions and issues
## General
**Q: What is Percify?**\
A platform for generating, animating, and voicing AI avatars with a transparent credit model.
**Q: Do credits expire?**\
Not currently. Future enterprise tiers may introduce rollover policies.
## Credits & Billing
**Q: Why did my credits decrease unexpectedly?**\
Likely due to longer video/audio durations. Check cost preview before confirming.
**Q: Can I reserve credits for queued jobs?**\
Reservation is a planned feature; today credits debit only on success.
## Generation
**Q: Outputs look repetitive—how to diversify?**\
Add action or environment keywords; refine with style adjustments.
**Q: Video feels choppy.**\
Use parallax or subtle pan styles; avoid extreme zoom on short clips.
## Voice
**Q: Audio has metallic noise.**\
Source sample quality too low. Re-record in a quiet space at higher bitrate.
**Q: Speech pacing is off.**\
Add punctuation for natural prosody.
## API
**Q: Getting 401 Unauthorized.**\
Missing or invalid `Authorization` header. Regenerate the key if unsure.
**Q: Receiving 403 despite valid key.**\
Account may be banned. See \[/percify/security].
**Q: How to paginate feed results?**\
Use `?page` or cursor-based endpoints (future). Estimated counts provided to avoid heavy total scans.
## Performance
**Q: Why is dashboard slow after large imports?**\
Indexes may not exist or need ANALYZE. Re-run optimization migration and monitor timings.
**Q: Video generation queued.**\
Peak concurrency; retry later or shorten duration.
## Safety & Moderation
**Q: Can I appeal a ban?**\
Yes—contact support with your user handle and reason.
**Q: How do I hide content?**\
Set avatar/video visibility to Private; remains accessible to you via API.
## Troubleshooting Table
| Symptom | Likely Cause | Fix |
| ------------------ | ---------------------------- | --------------------------- |
| 401 errors | Missing auth header | Add `Authorization: Bearer` |
| High credit usage | Long durations | Shorten video/audio |
| Slow feed | Cold cache / missing indexes | Verify DB optimization |
| Voice artifacts | Poor sample | Re-record |
| Desync audio/video | Length mismatch | Trim or re-generate |
| Banned response | Policy violation | Contact support |
## Support Channels
* Email (dashboard Support link)
* Future: Community forum & status page
## Related Pages
* \[/quickstart]
* \[/percify/credits]
* \[/percify/performance]
***
Need more help? Reach out via support.
# Image to Video
Source: https://docs.percify.io/percify/image-to-video
Transform static avatar images into dynamic animated video clips
## Overview
Percify's Image-to-Video feature brings your static avatars to life with AI-powered animation. Convert any avatar image into a short video clip with natural motion, lip-sync capabilities, and customizable duration.
Add motion to static images in seconds
Generate clips from 1 to 30 seconds
AI-powered natural movement and expressions
Perfect for adding voice tracks
## How It Works
The Image-to-Video pipeline uses advanced AI models to:
1. Analyze the input image structure and features
2. Generate intermediate frames with natural motion
3. Apply facial animations and subtle movements
4. Render smooth transitions at 30fps
5. Optimize for web delivery and streaming
## Video Studio Tiers
### Basic Video Studio
* **Base Cost:** 30 credits (includes first 5 seconds)
* **Additional:** +6 credits per second after 5s
* **Max Duration:** 10 seconds
* **Quality:** 720p, 30fps
* **Motion:** Standard animation
* **Best for:** Social media, quick clips
### Reality Lab (Premium)
* **Base Cost:** 20 credits (includes first 5 seconds)
* **Additional:** +4 credits per second after 5s
* **Max Duration:** 30 seconds
* **Quality:** 1080p, 60fps option
* **Motion:** Cinematic, advanced expressions
* **Best for:** Professional content, presentations
## Credit Cost Formula
```
Total Cost = Base Cost + (Additional Seconds × Per-Second Rate)
```
### Examples
| Duration | Studio Type | Calculation | Total Credits |
| ---------- | ----------- | ------------- | ------------- |
| 3 seconds | Basic | 30 + (0 × 6) | 30 |
| 5 seconds | Basic | 30 + (0 × 6) | 30 |
| 8 seconds | Basic | 30 + (3 × 6) | 48 |
| 10 seconds | Basic | 30 + (5 × 6) | 60 |
| 3 seconds | Reality Lab | 20 + (0 × 4) | 20 |
| 10 seconds | Reality Lab | 20 + (5 × 4) | 40 |
| 15 seconds | Reality Lab | 20 + (10 × 4) | 60 |
**Cost Optimization:** Keep videos under 5 seconds to avoid per-second charges. Perfect for loops and social media clips!
## Creating a Video
Choose an avatar from your gallery or generate a new one in Avatar Studio
Click "Convert to Video" or navigate to Video Studio from the dashboard
* Set video duration (1-30 seconds)
* Choose studio tier (Basic or Reality Lab)
* Select motion style (subtle, moderate, dynamic)
* Add audio track (optional)
Click "Generate" and wait for processing (typically 30-60 seconds per 10s of video)
Review the generated video, make adjustments if needed, then download or publish
## Motion Styles
### Subtle Motion
* Gentle breathing animations
* Slight head movements
* Soft eye blinks
* **Best for:** Professional portraits, peaceful scenes
* **Processing:** Fastest generation
### Moderate Motion
* Natural head turns (±15°)
* Expression changes
* Hair and clothing physics
* **Best for:** Conversational clips, character introductions
* **Processing:** Standard speed
### Dynamic Motion
* Full range of motion
* Dramatic expressions
* Background parallax effects
* **Best for:** Action scenes, music videos, creative content
* **Processing:** Requires Reality Lab
## API Integration
### Generate Video from Avatar
```javascript Node.js theme={null}
const response = await fetch('https://api.percify.io/v1/videos/from-image', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.PERCIFY_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
imageId: 'avatar_123',
durationSeconds: 5,
studioTier: 'basic',
motionStyle: 'moderate',
outputFormat: 'mp4'
})
});
const video = await response.json();
console.log(`Video ID: ${video.id}, Status: ${video.status}`);
```
```python Python theme={null}
import os
from percify import Percify
client = Percify(api_key=os.environ['PERCIFY_API_KEY'])
video = client.videos.from_image(
image_id='avatar_123',
duration_seconds=5,
studio_tier='basic',
motion_style='moderate',
output_format='mp4'
)
print(f"Video ID: {video.id}, Status: {video.status}")
```
```bash cURL theme={null}
curl -X POST https://api.percify.io/v1/videos/from-image \
-H "Authorization: Bearer $PERCIFY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"imageId": "avatar_123",
"durationSeconds": 5,
"studioTier": "basic",
"motionStyle": "moderate",
"outputFormat": "mp4"
}'
```
### Check Video Status
```bash theme={null}
curl -X GET https://api.percify.io/v1/videos/video_456 \
-H "Authorization: Bearer $PERCIFY_API_KEY"
```
Response:
```json theme={null}
{
"id": "video_456",
"status": "completed",
"videoUrl": "https://cdn.percify.io/videos/video_456.mp4",
"thumbnailUrl": "https://cdn.percify.io/videos/video_456_thumb.jpg",
"durationSeconds": 5,
"resolution": "720p",
"fps": 30,
"fileSize": 2456789,
"creditCost": 30,
"createdAt": "2025-11-25T05:40:00Z",
"completedAt": "2025-11-25T05:40:45Z"
}
```
### Poll for Completion
```javascript theme={null}
async function waitForVideo(videoId) {
const maxAttempts = 60; // 5 minutes max
const pollInterval = 5000; // 5 seconds
for (let i = 0; i < maxAttempts; i++) {
const response = await fetch(
`https://api.percify.io/v1/videos/${videoId}`,
{
headers: { 'Authorization': `Bearer ${process.env.PERCIFY_API_KEY}` }
}
);
const video = await response.json();
if (video.status === 'completed') {
return video;
} else if (video.status === 'failed') {
throw new Error(`Video generation failed: ${video.error}`);
}
await new Promise(resolve => setTimeout(resolve, pollInterval));
}
throw new Error('Video generation timed out');
}
```
## Adding Audio Tracks
Combine your animated video with voice cloning for fully realized characters:
Create your base video animation
Use voice cloning or upload pre-recorded audio
Automatically align lip movements with speech
Export combined video with synchronized audio
### API Example with Audio
```javascript theme={null}
// 1. Generate video
const video = await client.videos.fromImage({
imageId: 'avatar_123',
durationSeconds: 8
});
// 2. Generate voice audio
const audio = await client.audio.generate({
text: 'Welcome to Percify! Create amazing AI avatars in seconds.',
voiceId: 'voice_default',
speed: 1.0
});
// 3. Sync audio with video (automatic lip-sync)
const syncedVideo = await client.videos.addAudio({
videoId: video.id,
audioId: audio.id,
enableLipSync: true
});
console.log(`Final video URL: ${syncedVideo.videoUrl}`);
```
## Advanced Features
### Background Replacement
Replace or remove backgrounds during video generation:
```javascript theme={null}
await client.videos.fromImage({
imageId: 'avatar_123',
durationSeconds: 5,
background: {
type: 'replacement',
imageUrl: 'https://example.com/custom-bg.jpg'
}
});
```
### Camera Motion
Add camera movements for cinematic effects:
```javascript theme={null}
await client.videos.fromImage({
imageId: 'avatar_123',
durationSeconds: 10,
cameraMotion: {
type: 'zoom-in',
intensity: 'subtle'
}
});
```
Available camera motions:
* `static` - No camera movement
* `zoom-in` - Gradual zoom toward subject
* `zoom-out` - Pull back reveal
* `pan-left` / `pan-right` - Horizontal camera movement
* `orbit` - 360° rotation around subject (Reality Lab only)
### Custom Frame Rate
Control video smoothness:
```javascript theme={null}
await client.videos.fromImage({
imageId: 'avatar_123',
durationSeconds: 5,
fps: 60, // 24, 30, or 60
studioTier: 'reality-lab' // 60fps requires Reality Lab
});
```
## Performance & Processing Times
| Duration | Studio Type | Typical Processing Time |
| -------- | ----------- | ----------------------- |
| 3-5s | Basic | 20-35 seconds |
| 6-10s | Basic | 40-75 seconds |
| 3-5s | Reality Lab | 35-60 seconds |
| 10-15s | Reality Lab | 90-150 seconds |
| 15-30s | Reality Lab | 3-5 minutes |
**Processing Priority:** Enterprise tier users receive priority processing with 2x faster generation times.
## Best Practices
* Use high-resolution avatars (1024x1024 or higher)
* Ensure clean, well-lit images
* Center the subject in frame
* Avoid cropped faces for best results
* 3-5s: Social media clips, loops
* 5-10s: Introductions, greetings
* 10-15s: Short messages, explanations
* 15-30s: Detailed presentations (Reality Lab only)
* Start with Basic Studio for testing
* Use Reality Lab for final productions
* Keep under 5s to minimize per-second charges
* Batch similar videos for workflow efficiency
* Download in highest quality available
* Apply color grading externally if needed
* Compress for web delivery (Percify provides optimized versions)
* Add captions for accessibility
## Output Formats & Specs
### Video Formats
* **MP4 (H.264):** Best compatibility, recommended for most uses
* **WebM (VP9):** Smaller file size, good for web embedding
* **MOV (ProRes):** High quality, for professional editing workflows (Reality Lab only)
### Technical Specifications
| Tier | Resolution | FPS | Bitrate | Codec |
| ----------- | ----------------- | ----- | -------- | ----------- |
| Basic | 720p (1280×720) | 30 | 2-4 Mbps | H.264 |
| Reality Lab | 1080p (1920×1080) | 30/60 | 5-8 Mbps | H.264/H.265 |
## Troubleshooting
| Issue | Cause | Solution |
| ------------------------ | ------------------------------- | ----------------------------------------------------------------- |
| Video stuck "processing" | Queue overload or long duration | Wait up to processing time estimate, contact support after 10 min |
| Artifacts or glitches | Low quality input image | Use higher resolution avatar, avoid heavily compressed images |
| Unnatural motion | Misaligned features | Regenerate avatar with clearer facial features |
| Audio out of sync | Timing mismatch | Re-run lip-sync with `enableLipSync: true` |
| Insufficient credits | Cost exceeds balance | Reduce duration or purchase more credits |
## Webhooks for Video Completion
Subscribe to webhooks to get notified when videos complete:
```javascript theme={null}
// Setup webhook endpoint
app.post('/webhooks/percify', (req, res) => {
const event = req.body;
if (event.type === 'video.completed') {
const video = event.data;
console.log(`Video ${video.id} completed: ${video.videoUrl}`);
// Process completed video
processVideo(video);
}
res.sendStatus(200);
});
```
Configure webhook URL in dashboard: Settings → Webhooks → Add Endpoint
## Use Cases
Create engaging profile videos and story content
Animated instructors and presenters
Dynamic ad creative and product demos
Character cutscenes and dialogue
Animated chatbot avatars
AI-generated performers and visuals
## Next Steps
Add voice to your videos
Complete API documentation
Understand video pricing
## Support
Questions about Image-to-Video? Check the [FAQ](/percify/faq) or contact [support@percify.io](mailto:support@percify.io).
# Payments & Billing
Source: https://docs.percify.io/percify/payments
Credit purchase, payment intents, and balance management
## Overview
Users acquire credits via one-off purchases or (future) subscription packs. Stripe Payment Intents are used to ensure strong idempotency and accurate post-payment credit allocation.
## Purchase Flow
1. User selects credit pack (e.g., 500, 1k, 5k)
2. Frontend creates Payment Intent via `/api/payments/create-intent`
3. User completes card authentication
4. Webhook listens for `payment_intent.succeeded`
5. Credits added to user balance transactionally
## Webhook Handling (Conceptual)
```typescript theme={null}
// stripe-webhook.ts
if (event.type === 'payment_intent.succeeded') {
const intent = event.data.object;
const userId = intent.metadata.userId;
const packId = intent.metadata.packId;
await allocateCredits(userId, packId, intent.id);
}
```
## Idempotency & Safety
| Concern | Mitigation |
| ------------------------------- | ------------------------------------- |
| Double credit allocation | Store processed intent IDs |
| Failed payment after UI success | Rely solely on webhook event |
| Currency mismatches | Validate amount vs pack definition |
| Refund adjustments | Implement reverse credit transactions |
## Credit Packs Example
| Pack | Credits | Price (USD) | Effective / Credit |
| ------- | ---------- | ----------- | ------------------ |
| Starter | 500 | \$10 | \$0.020 |
| Creator | 1000 | \$18 | \$0.018 |
| Scale | 5000 | \$80 | \$0.016 |
| Custom | Negotiated | Varies | As agreed |
## Balance Endpoint
```bash theme={null}
curl -H "Authorization: Bearer $PERCIFY_API_KEY" \
https://api.percify.io/v1/credits/balance
```
Response:
```json theme={null}
{ "balance": 1240, "reserved": 120 }
```
Future reserved credits: jobs queued but not yet debited.
## UI Patterns
* Real-time balance badge near generation actions
* Pre-flight cost preview vs available balance
* Post-purchase toast with new balance & usage suggestions
## Failure Scenarios
| Scenario | Result | User Feedback |
| ------------------ | -------------------------- | ------------------------------ |
| Payment incomplete | No credit change | Show retry CTA |
| Webhook delayed | Temporary UI mismatch | Poll balance after short delay |
| Refund issued | Negative credit adjustment | Email + dashboard log |
## Audit Logging
Store credit allocation events: `{ id, userId, delta, source, referenceId, createdAt }` for reconciliation.
## Related Pages
* \[/percify/credits]
* \[/percify/faq]
***
Next: Platform safety at \[/percify/security].
# Performance & Scaling
Source: https://docs.percify.io/percify/performance
Optimizations for feed, dashboard, and generation throughput
## Overview
Percify performance strategy focuses on query consolidation, targeted indexing, and selective caching. Internal improvements documented in feed and dashboard optimization guides are summarized here for end users and integrators.
## Key Improvements
| Area | Technique | Result |
| ------------------ | ---------------------------- | ---------------------------------- |
| Dashboard Counts | UNION + filtered COUNT | 800ms → \~150ms |
| Feed/Explore Query | 9 targeted indexes | 1900ms → 500–700ms |
| Caching | CDN + stale-while-revalidate | Cache hits \~50–100ms |
| Counting Strategy | Approx reltuples estimates | Reduced expensive window functions |
## Dashboard Aggregation Pattern
```sql theme={null}
WITH counts AS (
SELECT
COUNT(*) FILTER (WHERE source = 'avatars') as avatar_count,
COUNT(*) FILTER (WHERE source = 'videos') as video_count,
COUNT(*) FILTER (WHERE source = 'voices') as voice_count,
COUNT(*) FILTER (WHERE source = 'likes') as liked_count
FROM (
SELECT 'avatars' FROM user_generated_avatars WHERE user_id = $1 AND COALESCE(hidden_from_feed,false)=false
UNION ALL
SELECT 'videos' FROM user_video_files WHERE user_id = $1
UNION ALL
SELECT 'voices' FROM user_audio_files WHERE user_id = $1
UNION ALL
SELECT 'likes' FROM avatar_likes WHERE user_id = $1
) combined
)
SELECT * FROM counts;
```
## Feed Query Principles
| Principle | Benefit |
| ----------------------------- | ------------------------- |
| Remove COUNT(\*) OVER | Avoid full-table scans |
| Replace EXISTS with LEFT JOIN | Utilize composite indexes |
| Partial indexes on visibility | Reduce filtered row set |
| Separate trending index | Faster popularity sorting |
## Caching Strategy
| Header | Value |
| --------------- | ------------------------------------------------- |
| `Cache-Control` | `public, max-age=300, stale-while-revalidate=600` |
| `Vary` | `Accept-Encoding` |
Use short TTL for freshness + long stale window for resilience.
## Monitoring Recommendations
* Log query durations >500ms
* Record generation job queue latency percentiles
* Track cache hit ratios per endpoint
## Scalability Tips for Integrators
| Scenario | Recommendation |
| ----------------------- | ---------------------------------------------- |
| Burst avatar generation | Queue jobs + show optimistic UI |
| Large feed pagination | Use estimated total counts for infinite scroll |
| High video durations | Batch long renders off peak |
| Heavy audio synthesis | Reuse voice profiles to skip cloning cost |
## Future Enhancements
* Materialized view fallback for extreme volumes
* Adaptive cost suggestions (dynamic UX based on balance)
* Background warm-up of popular assets
## Troubleshooting
| Symptom | Cause | Action |
| ----------------------- | ------------------------ | --------------------------------------- |
| Slow dashboard load | Missing indexes | Re-run optimization migration |
| Feed latency spikes | Cold cache / index bloat | VACUUM ANALYZE + ensure CDN caching |
| Generation queue delays | Concurrency saturation | Increase worker pool or throttle client |
## Related Pages
* \[/percify/architecture]
* \[/percify/credits]
* \[/percify/faq]
***
Have questions? See \[/percify/faq].
# Security & Compliance
Source: https://docs.percify.io/percify/security
User safety, ban system, and content controls
## Overview
Percify enforces safety through proactive account bans, visibility controls, and standardized API denial responses. This page summarizes mechanisms derived from the internal Ban System Guide.
## Ban System
| Field | Purpose |
| --------------- | --------------------------------- |
| `banned` | Boolean flag blocking feature use |
| `banned_at` | Timestamp of ban action |
| `banned_reason` | Human-readable rationale |
Utility functions:
* `checkUserBanned(userId)` returns status
* `requireNotBanned(userId)` throws if banned
* `createBannedUserResponse()` returns 403 standardized JSON
## Integration Pattern (Route Snippet)
```typescript theme={null}
const session = await auth.api.getSession({ headers: request.headers });
if (!session?.user) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
try { await requireNotBanned(session.user.id); }
catch { return createBannedUserResponse(); }
```
## Protected Endpoints (High Priority)
* Avatar generation & management
* Video & audio creation routes
* Profile update (handle, bio, avatar image)
## Visibility Controls
| State | Indexed | Public Feed | API Public | Owner Access |
| --------- | ------------- | ----------- | ---------- | ------------ |
| Draft | No | No | Auth only | Yes |
| Private | Yes (limited) | No | Auth only | Yes |
| Published | Yes | Yes | Public | Yes |
## Content Moderation (Recommended)
| Layer | Strategy |
| ---------------- | ----------------------------------------- |
| Prompt Filtering | Block disallowed terms pre-generation |
| Post-Gen Review | Flag suspicious outputs for manual audit |
| Rate Limits | Throttle abuse patterns |
| Ban Escalation | Automated triggers (credit exploit, spam) |
## Exploit Mitigations
Internal fixes cover:
* Credit real-time synchronization to stop race conditions
* Hardening against duplicate API calls (idempotency)
* Centralized cost logic removal of scattered constants
## Standard Error Responses
| Status | Case | Body |
| ------ | ------------ | -------------------------------------------------- |
| 401 | Missing auth | `{ "error": "Unauthorized" }` |
| 403 | Banned user | `{ "error": "Access denied", "reason": "banned" }` |
| 429 | Rate limit | `{ "error": "Too Many Requests" }` |
| 400 | Validation | `{ "error": "Invalid input" }` |
## Logging & Audit
Log structure suggestion:
```json theme={null}
{
"type": "ban_check",
"userId": "usr_123",
"result": "blocked",
"route": "/api/images/generate",
"timestamp": "2025-11-24T12:45:00Z"
}
```
## User Data Privacy (High Level)
* Minimal PII stored (email, optional display name)
* Media assets segregated by userId
* Token-based API access (no password sharing)
## Incident Response (Recommended Steps)
1. Detect anomaly (logs / alerts)
2. Temporarily ban account (script)
3. Archive related assets
4. Review root cause
5. Restore or escalate permanent ban
## Related Pages
* \[/percify/credits]
* \[/percify/performance]
* \[/percify/faq]
***
Performance safeguards next: \[/percify/performance].
# Use Cases
Source: https://docs.percify.io/percify/use-cases
Practical scenarios for leveraging Percify's avatar, video, and voice stack
## Overview
Percify enables rapid creation and personalization of media-rich AI avatars. Below are common patterns and how to implement them efficiently with credits and API endpoints.
## Marketing Content Generation
Produce a themed avatar series for a product launch:
1. Define brand style keywords ("neon accent", "clean tech", "gradient rim light").
2. Batch generate 4–6 avatar variants using Standard model for iteration.
3. Upgrade final selections with Premium for fidelity.
4. Animate top avatars into 5s clips (base cost only) for social teasers.
5. Optional voice line to reinforce messaging.
## Personalized User Profiles
Allow end users to create stylized AI profile pictures:
1. Collect initial prompt/style preferences.
2. Generate single Standard output (2 credits) for speed.
3. Offer refinement / premium upgrade path.
4. Store resulting avatarId and make it available in profile UI.
## Short Form Video Pipeline
Turn daily avatar prompts into snackable video content:
1. Morning batch of 10 prompts → images.
2. Select top 3 for animation (≤8s each).
3. Generate a short voice line per video.
4. Publish and tag for feed discovery.
## Educational Narration
Use consistent cloned voice across multiple learning clips:
1. Clone clear voice profile once (5 credits).
2. Generate short scripted audio lines; keep videos ≤10s for credit control.
3. Reuse same avatar style for brand continuity.
## Community Spotlight Features
Weekly spotlight on user-created avatars:
1. Query top liked avatars via feed endpoints.
2. Animate winning avatar with a "spotlight" motion style.
3. Attach congratulatory voice narration.
4. Publish as featured content (visibility flag).
## Multi-Character Scene (Avatar Cast)
Create a composite scene for storytelling:
1. Generate individual avatars separately.
2. Use Avatar Cast feature (30 credits) for combined scene.
3. Animate scene with subtle movement; optional group voice line.
## API Chaining Example
```mermaid theme={null}
graph LR;
A[Prompt Input] --> B[Image Generation];
B --> C[Video From Image];
C --> D[Audio Generation];
D --> E[Publish];
```
## Cost Optimization Tips
| Goal | Strategy |
| ----------------- | --------------------------------------- |
| Minimum spend | Use Standard model for initial draft |
| High fidelity | Switch to Premium only for final output |
| Video scale | Keep most clips at base 5s duration |
| Voice consistency | Reuse cloned voice; avoid re-cloning |
| Rapid iteration | Limit variants per prompt to 2–3 |
## Monitoring & Iteration
* Track credit usage spikes with dashboard summaries.
* Use performance logs to adjust video durations during peak load.
* Periodically rotate prompts for freshness in content feeds.
## Related Pages
* \[/percify/quickstart]
* \[/percify/avatar-studio]
* \[/percify/credits]
***
Need guidance for a custom workflow? See \[/percify/faq] or contact support.
# Voice Cloning
Source: https://docs.percify.io/percify/voice-cloning
Clone voices and generate natural speech for your AI avatars
## Overview
Percify's Voice Cloning technology enables you to create realistic voice replicas and generate natural-sounding speech in multiple languages. Perfect for adding personality to avatars, creating audio content, or building voice-enabled applications.
Human-like intonation and emotion
Support for 30+ languages
Clone voices from 15s samples
Control speed, pitch, and emotion
## How Voice Cloning Works
Provide a clean audio recording (15-60 seconds recommended)
Our models analyze vocal characteristics, tone, and patterns
Generate a unique voice ID you can reuse
Convert any text to speech using the cloned voice
## Voice Cloning Requirements
### Audio Sample Quality
**Optimal Conditions:**
* Clear, noise-free environment
* Professional or high-quality microphone
* Consistent volume level
* No background music or effects
* Sample rate: 44.1kHz or higher
* Format: WAV, MP3, or FLAC
* **Minimum:** 15 seconds (basic cloning)
* **Recommended:** 30-60 seconds (better quality)
* **Maximum:** 5 minutes (professional cloning)
Longer samples provide better voice fidelity and natural intonation.
Read clear, varied sentences that include:
* Different emotions (neutral, happy, serious)
* Various pitch ranges
* Natural pauses and breathing
* Complete sentences with proper intonation
**Example script:**
"Hello, I'm excited to try voice cloning with Percify. The technology is amazing and opens up so many creative possibilities. I can imagine using this for podcasts, videos, or even virtual assistants. Let's see how well it captures my unique voice characteristics."
## Pricing
### Voice Cloning (One-time per voice)
* **Cost:** 5 credits per voice clone
* **Includes:** Voice profile creation and storage
* **Reusable:** Generate unlimited audio with the same voice ID
### Audio Generation (Per use)
* **Base Cost:** 5 credits
* **Duration Cost:** +1 credit per second of generated audio
* **Formula:** `Total = 5 + (duration_seconds × 1)`
### Examples
| Duration | Calculation | Total Credits |
| ---------- | ------------- | ------------- |
| 5 seconds | 5 + (5 × 1) | 10 credits |
| 10 seconds | 5 + (10 × 1) | 15 credits |
| 30 seconds | 5 + (30 × 1) | 35 credits |
| 60 seconds | 5 + (60 × 1) | 65 credits |
| 2 minutes | 5 + (120 × 1) | 125 credits |
**Cost Optimization:** Clone a voice once (5 credits), then reuse it indefinitely. Only pay for generated audio duration.
## Creating a Voice Clone
### Via Dashboard
Click "Voice Cloning" from the main menu
Drag and drop or select your audio file (15s-5min)
Give your voice clone a memorable name
Select primary language for the voice
Click "Clone Voice" and wait 30-60 seconds for processing
### Via API
```javascript Node.js theme={null}
const fs = require('fs');
const FormData = require('form-data');
const form = new FormData();
form.append('audio', fs.createReadStream('voice-sample.wav'));
form.append('name', 'My Custom Voice');
form.append('language', 'en-US');
const response = await fetch('https://api.percify.io/v1/voices/clone', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.PERCIFY_API_KEY}`,
...form.getHeaders()
},
body: form
});
const voice = await response.json();
console.log(`Voice ID: ${voice.id}`);
```
```python Python theme={null}
import os
from percify import Percify
client = Percify(api_key=os.environ['PERCIFY_API_KEY'])
with open('voice-sample.wav', 'rb') as audio_file:
voice = client.voices.clone(
audio=audio_file,
name='My Custom Voice',
language='en-US'
)
print(f"Voice ID: {voice.id}")
```
```bash cURL theme={null}
curl -X POST https://api.percify.io/v1/voices/clone \
-H "Authorization: Bearer $PERCIFY_API_KEY" \
-F "audio=@voice-sample.wav" \
-F "name=My Custom Voice" \
-F "language=en-US"
```
Response:
```json theme={null}
{
"id": "voice_abc123",
"name": "My Custom Voice",
"language": "en-US",
"status": "completed",
"sampleDuration": 45.3,
"creditCost": 5,
"createdAt": "2025-11-25T05:45:00Z"
}
```
## Generating Speech
### Basic Text-to-Speech
```javascript Node.js theme={null}
const response = await fetch('https://api.percify.io/v1/audio/generate', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.PERCIFY_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
text: 'Welcome to Percify! Your AI-powered creative platform.',
voiceId: 'voice_abc123',
speed: 1.0,
pitch: 0,
outputFormat: 'mp3'
})
});
const audio = await response.json();
console.log(`Audio URL: ${audio.audioUrl}`);
```
```python Python theme={null}
from percify import Percify
import os
client = Percify(api_key=os.environ['PERCIFY_API_KEY'])
audio = client.audio.generate(
text='Welcome to Percify! Your AI-powered creative platform.',
voice_id='voice_abc123',
speed=1.0,
pitch=0,
output_format='mp3'
)
print(f"Audio URL: {audio.audio_url}")
```
```bash cURL theme={null}
curl -X POST https://api.percify.io/v1/audio/generate \
-H "Authorization: Bearer $PERCIFY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "Welcome to Percify! Your AI-powered creative platform.",
"voiceId": "voice_abc123",
"speed": 1.0,
"pitch": 0,
"outputFormat": "mp3"
}'
```
### Advanced Options
```javascript theme={null}
const audio = await client.audio.generate({
text: 'This is an exciting announcement!',
voiceId: 'voice_abc123',
// Voice modulation
speed: 1.1, // 0.5 to 2.0 (1.0 = normal)
pitch: 2, // -10 to +10 semitones
// Emotion & style
emotion: 'excited', // neutral, happy, sad, excited, calm
emphasis: ['exciting', 'announcement'], // Words to emphasize
// Output options
outputFormat: 'mp3', // mp3, wav, ogg
sampleRate: 44100, // 22050, 44100, 48000
bitrate: 192 // kbps for mp3
});
```
## Supported Languages
* `en-US` - American English
* `en-GB` - British English
* `en-AU` - Australian English
* `en-CA` - Canadian English
* `en-IN` - Indian English
* `es-ES` - Spanish (Spain)
* `es-MX` - Spanish (Mexico)
* `fr-FR` - French
* `de-DE` - German
* `it-IT` - Italian
* `pt-PT` - Portuguese (Portugal)
* `pt-BR` - Portuguese (Brazil)
* `pl-PL` - Polish
* `nl-NL` - Dutch
* `ru-RU` - Russian
* `zh-CN` - Mandarin Chinese (Simplified)
* `zh-TW` - Mandarin Chinese (Traditional)
* `ja-JP` - Japanese
* `ko-KR` - Korean
* `hi-IN` - Hindi
* `th-TH` - Thai
* `vi-VN` - Vietnamese
* `id-ID` - Indonesian
* `ar-SA` - Arabic
* `tr-TR` - Turkish
* `sv-SE` - Swedish
* `da-DK` - Danish
* `no-NO` - Norwegian
* `fi-FI` - Finnish
Language detection is automatic based on input text. Specify language explicitly for best results with multilingual content.
## Preset Voices
Don't have a voice sample? Use our preset voices:
Deep, authoritative, news anchor style
Clear, confident, corporate presenter
Warm, approachable, conversational
Upbeat, energetic, engaging
Storytelling, documentary style
Various character archetypes
Access preset voices:
```javascript theme={null}
const audio = await client.audio.generate({
text: 'Your message here',
voiceId: 'preset-professional-male',
// or: preset-professional-female, preset-friendly-male, etc.
});
```
## Combining Voice with Video
Create fully animated, voiced avatar videos:
```javascript theme={null}
// 1. Clone voice (one-time)
const voice = await client.voices.clone({
audio: voiceSample,
name: 'Character Voice'
});
// 2. Generate avatar video
const video = await client.videos.fromImage({
imageId: 'avatar_123',
durationSeconds: 8
});
// 3. Generate speech audio
const audio = await client.audio.generate({
text: 'Welcome to our platform! I\'m your AI guide.',
voiceId: voice.id
});
// 4. Sync audio with video (automatic lip-sync)
const finalVideo = await client.videos.addAudio({
videoId: video.id,
audioId: audio.id,
enableLipSync: true
});
console.log(`Complete video: ${finalVideo.videoUrl}`);
```
## Voice Management
### List Your Voices
```bash theme={null}
curl -X GET https://api.percify.io/v1/voices \
-H "Authorization: Bearer $PERCIFY_API_KEY"
```
### Update Voice Metadata
```javascript theme={null}
await client.voices.update('voice_abc123', {
name: 'Updated Voice Name',
description: 'Professional narrator voice for documentaries',
tags: ['professional', 'narrator', 'documentary']
});
```
### Delete Voice
```bash theme={null}
curl -X DELETE https://api.percify.io/v1/voices/voice_abc123 \
-H "Authorization: Bearer $PERCIFY_API_KEY"
```
## Audio Quality Optimization
* **MP3:** Best for web/streaming (smaller files)
* **WAV:** Highest quality, uncompressed (large files)
* **OGG:** Good compression, open format
Choose based on your use case and delivery method.
Higher values = better quality but larger files
**Recommended settings:**
* Web/mobile: 44.1kHz, 128kbps MP3
* Professional: 48kHz, 320kbps MP3 or WAV
* Podcast: 44.1kHz, 192kbps MP3
Percify automatically applies:
* Noise reduction
* Volume normalization
* De-essing (reduces harsh 's' sounds)
* Breath removal (optional)
Disable with `applyProcessing: false` for raw output.
## Advanced Features
### SSML Support
Use Speech Synthesis Markup Language for fine control:
```xml theme={null}
Welcome to Percify!
Create amazing content
with AI-powered tools.
```
```javascript theme={null}
const audio = await client.audio.generate({
text: ssmlContent,
voiceId: 'voice_abc123',
textFormat: 'ssml'
});
```
### Phoneme-Level Control
Specify exact pronunciation:
```json theme={null}
{
"text": "Welcome to Percify",
"phonemes": {
"Percify": "ˈpɜːrsɪfaɪ"
}
}
```
### Voice Mixing
Combine multiple voices in one audio:
```javascript theme={null}
const audio = await client.audio.generateMultiVoice({
segments: [
{ text: 'Hello, I\'m Sarah.', voiceId: 'voice_sarah' },
{ text: 'And I\'m John.', voiceId: 'voice_john' },
{ text: 'Together we\'ll guide you.', voiceId: 'both' }
]
});
```
## Use Cases
YouTube videos, podcasts, audiobooks
Online courses, training materials
Screen readers, audio descriptions
Character dialogue, narration
Chatbots, voice interfaces
Ads, promotional content
## Best Practices
**Recording Tips:**
* Use a pop filter to reduce plosives (p, b sounds)
* Record in a quiet, carpeted room
* Maintain consistent distance from mic (6-12 inches)
* Speak naturally, don't over-enunciate
* Do multiple takes and choose the best
**Content Policy:**
* Only clone voices you have permission to use
* Don't impersonate others without consent
* No deceptive or fraudulent use
* Comply with local voice biometric laws
* Clearly disclose AI-generated content when required
## Troubleshooting
| Issue | Cause | Solution |
| -------------------- | -------------------- | ---------------------------------------------- |
| Robotic sound | Poor quality sample | Use longer, clearer audio sample |
| Wrong pronunciation | Text ambiguity | Use SSML or phonemes for clarity |
| Volume inconsistency | Unprocessed output | Enable `applyProcessing: true` |
| Generation fails | Unsupported language | Check language code, use preset if unavailable |
| Audio cuts off | Duration limit hit | Split into multiple requests, concatenate |
## API Rate Limits
| Tier | Cloning | Generation | Concurrent |
| ---------- | --------- | ---------- | ---------- |
| Free | 5/day | 100/day | 2 |
| Pro | 50/day | 1000/day | 5 |
| Enterprise | Unlimited | Unlimited | 20 |
## Next Steps
Combine voice with animation
Complete API docs
Voice pricing details
## Support
Need help with voice cloning? Visit the [FAQ](/percify/faq) or email [support@percify.io](mailto:support@percify.io).
# Percify Quickstart
Source: https://docs.percify.io/quickstart
From signup to your first animated, voiced avatar in minutes
## Overview
Follow these steps to experience the full Percify creation loop quickly.
Sign up on the Percify dashboard. Your starter credits appear automatically; if not, visit Billing to purchase a pack.
Navigate to Settings → API Keys. Create a key and store it securely. Use it in the `Authorization: Bearer ` header for server-side calls.
Use the Avatar Studio UI or call the image generation endpoint:
```bash theme={null}
curl -X POST https://api.percify.io/v1/images/generate \
-H "Authorization: Bearer $PERCIFY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"prompt":"futuristic portrait, soft rim light"}'
```
Response includes `id`, `status`, and `creditCost`. Track generation with the returned ID if asynchronous.
Adjust prompt, style, or upscale. Publishing marks the avatar as visible in feed/explore unless you set private visibility. Private avatars still usable for video/voice pipelines.
In Studio select "Image to Video". Each clip consumes base + per‑second credits. Keep under 5s for minimal cost. See \[/percify/image-to-video] for pricing formula.
Upload a clean sample (≥15s). Voice cloning costs base credits; generating speech adds duration‑based cost. Attach voice track to video from the Studio timeline.
Use public asset URLs or fetch metadata:
```bash theme={null}
curl -H "Authorization: Bearer $PERCIFY_API_KEY" \
https://api.percify.io/v1/avatars/{avatarId}
```
Embed in your app or generate derived assets.
Dashboard shows per‑feature consumption. For programmatic checks:
```bash theme={null}
curl -H "Authorization: Bearer $PERCIFY_API_KEY" \
https://api.percify.io/v1/credits/balance
```
## Credit Cost Cheatsheet
| Feature | Base | Variable | Notes |
| -------------------------------- | ---- | ---------- | --------------------- |
| Image Standard (Flux) | 2 | — | Per output |
| Image Premium (Imagen3/Reality4) | 5 | — | Per output |
| Percify Yourself | 10 | — | Photo → avatar |
| Avatar Cast | 30 | — | Multi‑character scene |
| Voice Cloning | 5 | — | One-time per clone |
| Audio Generation | 5 | +1/sec | Includes TTS duration |
| Video Studio | 30 | +6/sec >5s | First 5s in base |
| Reality Lab | 20 | +4/sec >5s | Cinematic mode |
Full rationale: \[/percify/credits].
## Minimal End-to-End Example (Server)
```typescript theme={null}
// generate-avatar.ts
import fetch from 'node-fetch';
const API = 'https://api.percify.io/v1';
const KEY = process.env.PERCIFY_API_KEY!;
async function run() {
// 1. Image
const imgRes = await fetch(`${API}/images/generate`, {
method: 'POST',
headers: { 'Authorization': `Bearer ${KEY}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ prompt: 'celestial explorer portrait, nebula background' })
}).then(r => r.json());
// 2. Video from image
const vidRes = await fetch(`${API}/videos/from-image`, {
method: 'POST',
headers: { 'Authorization': `Bearer ${KEY}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ imageId: imgRes.id, durationSeconds: 5 })
}).then(r => r.json());
// 3. Voice line
const voiceRes = await fetch(`${API}/audio/generate`, {
method: 'POST',
headers: { 'Authorization': `Bearer ${KEY}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ text: 'Exploring the stars with Percify.', voiceId: 'default' })
}).then(r => r.json());
console.log({ imgRes, vidRes, voiceRes });
}
run();
```
## Next Steps
Workflows & UI
Pricing logic
Authenticate calls
## Troubleshooting
| Issue | Cause | Fix |
| --------------------- | --------------------------------- | ---------------------------------- |
| 401 Unauthorized | Missing/invalid API key | Regenerate key in dashboard |
| Insufficient credits | Balance below feature cost | Purchase credits or lower duration |
| Slow video generation | High concurrency or long duration | Reduce length or queue workflows |
| Voice artifacting | Low quality source sample | Re‑record with clean background |
See \[/percify/faq] for more.