Documentation
FRANKLAB API

Connect to the API

Connect your application: authentication, requests, files and results.

Open .md
Open in AI

Work with an AI assistant

Shares the current documentation without your keys. Long sections are copied in full for you to paste into chat.

Cursor and Claude Code accept short prompts in links. For long sections, ChatGPT and Antigravity, paste the copied documentation manually.

Ask support

Use Make module operations directly from your server, script, or an n8n HTTP Request node. Make is not required to send HTTP requests.

1. Get a key and check your balance

Register with Apergrex, then create a dedicated integration key in Settings → API. Top up in the cabinet or through the payment API. Generation and processing use your account balance.

Base URL:

text
https://apergrex.ru/franklab/api

Append guide paths to this base. For example, /franklab/jobs/image becomes https://apergrex.ru/franklab/api/franklab/jobs/image: the repeated franklab is intentional.

bash
read -rsp 'API key: ' FRANKLAB_KEY; echo
export FRANKLAB_KEY
export FRANKLAB_BASE_URL='https://apergrex.ru/franklab/api'
curl --fail-with-body --max-time 30 \
  -H "X-API-Key: ${FRANKLAB_KEY:?Set your API key}" \
  "$FRANKLAB_BASE_URL/v1/billing/balance"

Keep the key in server-side secrets. Never put it in URLs, browser code, logs, or AI conversations. Each guide specifies the authentication header: utility Make modules use Authorization: Bearer; many generation routes use X-API-Key.

2. Choose an operation and its contract

TaskGuideModules
Generate or edit videoVideo generationAlibaba Video, HEYGEN AGENT, MARS, MOON, MiniMax, OMNI, SATURN, VECTOR, VENUS, X
Generate images, text, speech or music; prepare elementsImages, text and audioAlibaba Image, JUPITER, KUSOK, MOON GPT, ORKESTR, VOLNA
Process files, edit media, add subtitles or audit SEOUtilities and montageC2PA, FORSAJ, HOLST, INDEXLIFT, KLEY, OVERLAY, PLASTINKA, SPEKTR, SUFLER

A Make label helps you find an operation, but is not necessarily a REST parameter. Use the values in the operation example, not dropdown labels or {{parameters.…}} expressions. One module may call multiple routes with different response shapes.

3. Prepare input files

If an operation accepts imageUrl, videoUrl or another URL field, you can use a direct public HTTPS link without uploading first. A cloud-storage link must return the actual file without login, cookies or an authorization header. A sharing page, HTML preview, local path or browser blob: URL is not a media file link. Keep the link accessible for the whole processing period; an expired link must be replaced before a new request. The import endpoint below rejects private/local addresses and unsafe redirects.

For a local file, use multipart upload. Replace input.png with your file:

bash
set -e
curl --fail-with-body --max-time 120 \
  -H "Authorization: Bearer ${FRANKLAB_KEY:?Set your API key}" \
  -F 'file=@./input.png;type=image/png' \
  "$FRANKLAB_BASE_URL/franklab/jobs/upload" \
  -o upload.json
jq -e '.success == true and (.data.storedFileId | type == "string")' upload.json >/dev/null
jq '.data | {url,storedFileId,mimeType,sizeBytes,expiresAt}' upload.json

Do not set Content-Type: application/json for multipart: cURL supplies the boundary. Upload returns {success:true,data:{url,storedFileId,mimeType,sizeBytes,expiresAt}}. The existing data.url goes into URL fields; data.storedFileId is the file ID belonging to your account. Uploaded source files are retained for 7 days. Upload accepts supported image/video/audio files up to 150 MiB and does not convert their format; each processing operation can impose stricter limits.

Import a URL or inspect an uploaded file

Some inputs, such as Alibaba firstFrame, need a descriptor with a file ID and measured dimensions. Use POST /franklab/jobs/import, authenticated with the same account key. Send kind and exactly one of url or storedFileId:

kindImport formatsMaximum file size
imagePNG, JPEG, WebP30 MiB
videoMP4, MOV, WebM100 MiB
audioSupported audio formats; keep within the target operation's format limits50 MiB
documentPDF, TXT, MD20 MiB

Export Word, Excel, PowerPoint and other office documents as PDF before importing them. Import inspects the actual bytes; it does not transcode a file or make it compatible with every model.

Import an image from a direct link:

bash
set -e
jq -n --arg url 'https://media.example.com/product-front.png' \
  '{url:$url,kind:"image"}' > import-request.json
curl --fail-with-body --max-time 180 \
  -H "Authorization: Bearer ${FRANKLAB_KEY:?Set your API key}" \
  -H 'Content-Type: application/json' \
  --data-binary @import-request.json \
  "$FRANKLAB_BASE_URL/franklab/jobs/import" \
  -o imported.json
jq -e '.success == true and (.data.storedFileId | type == "string")' imported.json >/dev/null
jq '.data' imported.json

For an image you already uploaded, use the saved response to import by ID instead:

bash
set -e
jq -e '.data | {storedFileId,kind:"image"} | select(.storedFileId | type == "string" and length > 0)' \
  upload.json > import-request.json
curl --fail-with-body --max-time 180 \
  -H "Authorization: Bearer ${FRANKLAB_KEY:?Set your API key}" \
  -H 'Content-Type: application/json' \
  --data-binary @import-request.json \
  "$FRANKLAB_BASE_URL/franklab/jobs/import" \
  -o imported.json
jq -e '.success == true and (.data.storedFileId | type == "string")' imported.json >/dev/null
jq '.data' imported.json

The response is {success:true,data:{storedFileId,url,mimeType,sizeBytes,width?,height?,durationSeconds?,fps?,pageCount?}}. Optional fields appear when applicable to the inspected file: image dimensions, video dimensions/duration/frame rate, audio duration or PDF page count. Use the measured fields returned by the API, rather than guessed values. A newly imported source is retained for 14 days; inspecting an existing uploaded file does not extend its original expiry. See the Alibaba first-frame example for building a descriptor from this response.

Qwen image editing

For POST /make/alibaba/images, the simplest input is editImageUrls: 1–3 direct HTTPS URLs, PNG/JPEG/WebP, 10 MiB maximum per image. Qwen's limit is lower than the generic image-import limit. The server imports these references for your account:

json
{
  "model": "qwen-image-3.0",
  "operation": "image_edit",
  "prompt": "Replace the background with a pale blue studio backdrop.",
  "width": 1024,
  "height": 1024,
  "editImageUrls": ["https://media.example.com/product-front.png"]
}

Alternatively, collect uploaded data.storedFileId values into editImageIds. For the single image in upload.json:

bash
jq -e '.data.storedFileId | select(type == "string" and length > 0) | {model:"qwen-image-3.0",operation:"image_edit",prompt:"Replace the background with a pale blue studio backdrop.",width:1024,height:1024,editImageIds:[.]}' \
  upload.json > qwen-request.json

Send exactly one of editImageUrls or editImageIds. Neither field is a MOON GPT file ID or a Make {value} object. Before submitting the generation, estimate it with the selected model, qwenOperation:"image_edit", imageCount, width, height and n; estimates do not download the references. See Qwen operations for the full request and result contract.

Other modules can use direct URLs, their own upload API or different IDs. Follow the input shape in the module guide; file IDs from separate systems are not interchangeable.

4. Estimate the cost and create one task

Use the estimate for the exact route, model and parameters. Compare it with available; the price list contains base rates, not a guaranteed personal quote. The operation guide notes when a separate estimator is absent; an unknown cost does not mean zero.

The complete MARS example covers balance → estimate → submit → status → video URL. Submission may reserve funds. Do not run every catalog example in sequence.

5. Retrieve the result

Save the returned ID immediately. Poll the matching operation's status route using the same account. Response formats differ:

FamilyIdentifier and result
MARS text2videodata.task_id, data.task_status; successful output at data.task_result.videos[0].url
Make jobs facadedata.taskId, data.status; output at data.result.downloadUrl
Other operationsFollow the module contract: synchronous response, separate task, or another output shape

Bound your poll count and wait time. Keep the ID when the wait expires and check it later. On a submission timeout, 5xx, or missing ID, do not automatically repeat POST: the server may have accepted the task. Check history and contact support. The payment API's Idempotency-Key does not make arbitrary generation routes idempotent.

Verify that the result is accessible. Download and decode media; inspect text responses. Reconcile the final charge against transactions. Estimate, reservation and final cost can differ.

Python: verify your connection

Uses the standard library with no extra packages. This example only reads the balance.

python
import json
import os
from urllib.request import Request, urlopen

base = "https://apergrex.ru/franklab/api"
request = Request(base + "/v1/billing/balance", headers={
    "X-API-Key": os.environ["FRANKLAB_KEY"],
})
with urlopen(request, timeout=30) as response:
    balance = json.load(response)
print({name: balance.get(name) for name in ("available", "reserved")})

For a generation JSON request, set method="POST", data=json.dumps(payload).encode() and Content-Type: application/json. Take the payload, submit path and status path from the module guide. Do not add automatic task-creation retries.

JavaScript: verify your connection

For server-side Node.js with built-in fetch. This example only reads the balance.

javascript
const key = process.env.FRANKLAB_KEY;
if (!key) throw new Error("Set FRANKLAB_KEY");
const base = "https://apergrex.ru/franklab/api";
const response = await fetch(`${base}/v1/billing/balance`, {
  headers: { "X-API-Key": key },
  redirect: "error",
  signal: AbortSignal.timeout(30000),
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const { available, reserved } = await response.json();
console.log({ available, reserved });

For a generation JSON request, add method: "POST", body: JSON.stringify(payload) and Content-Type: application/json. Before continuing, check both HTTP status and the contract's success/error fields.

Share documentation with AI

Each section supports opening, downloading and copying Markdown, and handing it to AI. Share the relevant family guide together with this connection guide. Insert the real API key only in your own environment after reviewing the generated code.

/en/docs/integration.md
Need help?Contact support