Quickstart
This guide creates a flow from a text prompt, checks its status, and downloads the generated 3D model.
Prerequisites
Before creating your first 3D model make sure to:
- Create a Generio account and an API key: Sign in at account.generio.ai, open Account -> API Keys, then click Add key and store the secret safely. For the full walkthrough, read Authentication.
- Keep your API key private: Store it in your local environment or an uncommitted
.envfile.
Install Dependencies
Choose the language or runtime you want to use. The cURL and wget snippets are written for macOS, Linux, and Git Bash on Windows. Backend JavaScript projects can use any framework or module style; the examples below use Node.js 18 or later with dotenv for loading environment variables.
curl --version
wget --version
pip install requests python-dotenv
npm install dotenv
php --version
Set Your API Key
Set GENERIO_API_KEY before making requests. On macOS, Linux, or Git Bash, use export. In Windows PowerShell, use $env:GENERIO_API_KEY.
export GENERIO_API_KEY="paste-your-key-here"
export GENERIO_API_KEY="paste-your-key-here"
# .env
GENERIO_API_KEY=paste-your-key-here
# .env
GENERIO_API_KEY=paste-your-key-here
export GENERIO_API_KEY="paste-your-key-here"
Create a Flow
Create a flow from the model_generate_fromprompt template. The example starts automatically because it includes the input prompt in the create request.
curl -X POST "https://flows.generio.ai/flows" \
-H "Authorization: Bearer $GENERIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"template": "model_generate_fromprompt",
"parameters": {
"quality": "high"
},
"inputs": [
{
"data": "A modern office chair",
"additional": null
}
],
"additional": null
}'
wget --method=POST \
--header="Authorization: Bearer $GENERIO_API_KEY" \
--header="Content-Type: application/json" \
--body-data='{
"template": "model_generate_fromprompt",
"parameters": {
"quality": "high"
},
"inputs": [
{
"data": "A modern office chair",
"additional": null
}
],
"additional": null
}' \
"https://flows.generio.ai/flows" -O -
from dotenv import load_dotenv
import os
import requests
load_dotenv()
api_key = os.getenv("GENERIO_API_KEY")
base_url = "https://flows.generio.ai"
headers = {"Authorization": f"Bearer {api_key}"}
payload = {
"template": "model_generate_fromprompt",
"parameters": {
"quality": "high"
},
"inputs": [
{
"data": "A modern office chair",
"additional": None
}
],
"additional": None
}
response = requests.post(f"{base_url}/flows", headers=headers, json=payload)
response.raise_for_status()
flow_id = response.json()["flow_id"]
print(f"Flow created: {flow_id}")
import "dotenv/config";
const apiKey = process.env.GENERIO_API_KEY;
const baseUrl = "https://flows.generio.ai";
const response = await fetch(`${baseUrl}/flows`, {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
template: "model_generate_fromprompt",
parameters: {
quality: "high",
},
inputs: [
{
data: "A modern office chair",
additional: null,
},
],
additional: null,
}),
});
if (!response.ok) {
throw new Error(`Failed to create flow: ${response.status}`);
}
const { flow_id: flowId } = await response.json();
console.log(`Flow created: ${flowId}`);
<?php
$apiKey = getenv("GENERIO_API_KEY");
$baseUrl = "https://flows.generio.ai";
if (!$apiKey) {
throw new RuntimeException("Set GENERIO_API_KEY before running this script.");
}
function generioRequest(string $method, string $url, string $apiKey, ?array $payload = null): array
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $apiKey,
"Content-Type: application/json"
]);
if ($payload !== null) {
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
}
$response = curl_exec($ch);
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curlError = curl_error($ch);
curl_close($ch);
if ($response === false) {
throw new RuntimeException("Request failed: " . $curlError);
}
$data = json_decode($response, true);
if ($data === null && json_last_error() !== JSON_ERROR_NONE) {
throw new RuntimeException("Invalid JSON response: " . $response);
}
if ($statusCode < 200 || $statusCode >= 300) {
throw new RuntimeException("API request failed with HTTP " . $statusCode . ": " . $response);
}
return $data;
}
$payload = [
"template" => "model_generate_fromprompt",
"parameters" => [
"quality" => "high"
],
"inputs" => [
[
"data" => "A modern office chair",
"additional" => null
]
],
"additional" => null
];
$data = generioRequest("POST", $baseUrl . "/flows", $apiKey, $payload);
if (empty($data["flow_id"])) {
throw new RuntimeException("Create flow response did not include flow_id: " . json_encode($data));
}
$flowId = $data["flow_id"];
echo "Flow created: " . $flowId . PHP_EOL;
?>
Copy the returned flow_id. You will use it in the next requests.
Check the Flow Status
Poll the flow until state becomes completed, failed, or aborted.
FLOW_ID="paste-flow-id-here"
curl -X GET "https://flows.generio.ai/flows/$FLOW_ID" \
-H "Authorization: Bearer $GENERIO_API_KEY" \
-H "Content-Type: application/json"
FLOW_ID="paste-flow-id-here"
wget --header="Authorization: Bearer $GENERIO_API_KEY" \
--header="Content-Type: application/json" \
"https://flows.generio.ai/flows/$FLOW_ID" -O -
import time
print("Processing...")
while True:
response = requests.get(f"{base_url}/flows/{flow_id}", headers=headers)
response.raise_for_status()
status = response.json()
state = status["state"]
progress = status["progress"]
progress_text = "In Progress" if progress == 0 else "Complete"
print(f"Status: {state} - {progress_text}")
if state in ["completed", "failed", "aborted"]:
break
time.sleep(5)
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
console.log("Processing...");
let status;
while (true) {
const statusResponse = await fetch(`${baseUrl}/flows/${flowId}`, {
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
});
if (!statusResponse.ok) {
throw new Error(`Failed to check status: ${statusResponse.status}`);
}
status = await statusResponse.json();
const progressText = status.progress === 0 ? "In Progress" : "Complete";
console.log(`Status: ${status.state} - ${progressText}`);
if (["completed", "failed", "aborted"].includes(status.state)) {
break;
}
await sleep(5000);
}
<?php
echo "Processing..." . PHP_EOL;
do {
$status = generioRequest("GET", $baseUrl . "/flows/" . $flowId, $apiKey);
if (!isset($status["state"])) {
throw new RuntimeException("Status response did not include state: " . json_encode($status));
}
$progress = $status["progress"] ?? 0;
$progressText = $progress >= 1 ? "Complete" : "In Progress";
echo "Status: " . $status["state"] . " - " . $progressText . PHP_EOL;
if (in_array($status["state"], ["completed", "failed", "aborted"], true)) {
break;
}
sleep(5);
} while (true);
?>
Download the 3D Model
Once the flow is completed, list the output assets and download the generated model.
FLOW_ID="paste-flow-id-here"
curl -X GET "https://flows.generio.ai/flows/$FLOW_ID/outputs" \
-H "Authorization: Bearer $GENERIO_API_KEY" \
-H "Content-Type: application/json"
FLOW_ID="paste-flow-id-here"
wget --header="Authorization: Bearer $GENERIO_API_KEY" \
--header="Content-Type: application/json" \
"https://flows.generio.ai/flows/$FLOW_ID/outputs" -O -
import base64
if status["state"] == "completed":
response = requests.get(f"{base_url}/flows/{flow_id}/outputs", headers=headers)
response.raise_for_status()
outputs = response.json()["outputs"]
if not outputs:
raise RuntimeError("No outputs generated")
for output in outputs:
model_response = requests.get(
f"{base_url}/flows/{flow_id}/outputs/{output['asset_id']}?include_data=true",
headers=headers
)
model_response.raise_for_status()
data_uri = model_response.json()["data"]
base64_data = data_uri.split(",", 1)[1]
binary_data = base64.b64decode(base64_data)
filename = f"model_{output['asset_id']}.glb"
with open(filename, "wb") as file:
file.write(binary_data)
print(f"Saved model: {filename}")
else:
print(f"Flow ended with state: {status['state']}")
const { writeFile } = await import("node:fs/promises");
if (status.state === "completed") {
const outputsResponse = await fetch(`${baseUrl}/flows/${flowId}/outputs`, {
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
});
if (!outputsResponse.ok) {
throw new Error(`Failed to list outputs: ${outputsResponse.status}`);
}
const { outputs } = await outputsResponse.json();
if (!outputs.length) {
throw new Error("No outputs generated");
}
for (const output of outputs) {
const modelResponse = await fetch(
`${baseUrl}/flows/${flowId}/outputs/${output.asset_id}?include_data=true`,
{
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
},
);
if (!modelResponse.ok) {
throw new Error(`Failed to download output: ${modelResponse.status}`);
}
const { data } = await modelResponse.json();
const base64Data = data.split(",", 2)[1];
const filename = `model_${output.asset_id}.glb`;
await writeFile(filename, Buffer.from(base64Data, "base64"));
console.log(`Saved model: ${filename}`);
}
} else {
console.log(`Flow ended with state: ${status.state}`);
}
<?php
if ($status["state"] === "completed") {
$outputsResponse = generioRequest("GET", $baseUrl . "/flows/" . $flowId . "/outputs", $apiKey);
$outputs = $outputsResponse["outputs"] ?? [];
if (count($outputs) === 0) {
throw new RuntimeException("No outputs generated");
}
$outputDir = __DIR__ . "/outputs";
if (!is_dir($outputDir)) {
mkdir($outputDir, 0777, true);
}
echo "Saving files in: " . $outputDir . PHP_EOL;
foreach ($outputs as $output) {
$assetId = $output["asset_id"];
$url = $baseUrl . "/flows/" . $flowId . "/outputs/" . $assetId . "?include_data=true";
$model = generioRequest("GET", $url, $apiKey);
if (empty($model["data"])) {
throw new RuntimeException("Output response did not include data for asset " . $assetId);
}
$dataUri = $model["data"];
$base64Parts = explode(",", $dataUri, 2);
if(count($base64Parts) < 2) {
throw new RuntimeException("Unexpected data format for asseet " . $assetId);
}
$base64Data = $base64Parts[1];
$filename = $outputDir . "/model_" . $assetId . ".glb";
file_put_contents($filename, base64_decode($base64Data));
echo "Saved model: " . $filename . PHP_EOL;
}
} else {
echo "Flow ended with state: " . $status["state"] . PHP_EOL;
}
?>
For cURL, wget, and PowerShell, copy an asset_id from the outputs response and request the asset with include_data=true:
FLOW_ID="paste-flow-id-here"
ASSET_ID="paste-asset-id-here"
curl -X GET "https://flows.generio.ai/flows/$FLOW_ID/outputs/$ASSET_ID?include_data=true" \
-H "Authorization: Bearer $GENERIO_API_KEY" \
-H "Content-Type: application/json"
FLOW_ID="paste-flow-id-here"
ASSET_ID="paste-asset-id-here"
wget --header="Authorization: Bearer $GENERIO_API_KEY" \
--header="Content-Type: application/json" \
"https://flows.generio.ai/flows/$FLOW_ID/outputs/$ASSET_ID?include_data=true" -O -
# Python downloads the model in the previous step.
// JavaScript downloads the model in the previous step.
<?php
// PHP downloads the model in the previous step.
?>
Example Output
Here is what you should see after you run the example with a valid API key:

A 3D model will be generated as a .glb file.

What's Next?
- You can find all available endpoints in All Endpoints.
- Learn more about the core concepts in Flow.
- Review state transitions in Flow Lifecycle.
- Diagnose issues in Troubleshooting.
- We appreciate your feedback! If you encounter any errors, bugs, or inconsistencies please reach out to us. Join our Discord server or contact us.