Simplified Workflow: Jobs Endpoint
Beta: The Glossi API is currently in beta. Endpoints, request/response formats, and behavior may change as we iterate. If you run into issues or have feedback, reach out at support@glossi.io.
The Jobs endpoint combines the entire workflow into fewer steps. Instead of managing each step individually, you create a single job that orchestrates everything.
Why Use Jobs?
| Traditional Flow (8+ steps) | Jobs Flow (4 steps) |
|---|---|
| Create model → Upload → Confirm → Poll status → Create project → Render → Poll render | Create job → Upload → Confirm → Poll until done |
Step 1: Create a Job
Endpoint:
POST https://api.glossi.app/api/v1/jobsHeaders:
| Header | Value |
|---|---|
X-API-Key | Your API key |
Content-Type | application/json |
Body (without rendering):
{
"models": [
{ "fileName": "chair.glb", "fileType": "glb" },
{ "fileName": "table.glb", "fileType": "glb" }
],
"templateId": "your-template-uuid",
"createProjects": true
}Body (with rendering):
{
"models": [
{ "fileName": "chair.glb", "fileType": "glb" }
],
"templateId": "your-template-uuid",
"renderSettings": {
"renderBookmarks": true,
"imageQuality": 1
}
}Response:
{
"jobId": "job-uuid",
"status": "AWAITING_UPLOADS",
"models": [
{
"id": "model-1-uuid",
"fileName": "chair.glb",
"uploadUrl": "https://s3.../signed-url-1",
"uploadKey": "workspaces/.../model.glb"
},
{
"id": "model-2-uuid",
"fileName": "table.glb",
"uploadUrl": "https://s3.../signed-url-2",
"uploadKey": "workspaces/.../model.glb"
}
]
}Step 2: Upload Files to S3
Upload each file directly to its signed URL. This request goes directly to S3, not to Glossi's API.
Endpoint:
PUT <uploadUrl from Step 1 response>Headers:
| Header | Value |
|---|---|
Content-Type | model/gltf-binary (for GLB files) |
Body: Your binary file data
Note: Don't include your API key for this request - the signed URL already contains authentication.
A successful upload returns an empty response with status 200 OK.
Repeat this for each model in your job.
Step 3: Confirm Uploads
After uploading all files, tell the job that uploads are complete. This sets the file paths and advances the job to processing.
Endpoint:
POST https://api.glossi.app/api/v1/jobs/{jobId}/confirm-uploadsHeaders:
| Header | Value |
|---|---|
X-API-Key | Your API key |
Body: None required
Response:
{
"jobId": "job-uuid",
"status": "PROCESSING",
"modelsConfirmed": 2
}Step 4: Poll for Completion
The job automatically progresses through each phase. Poll this endpoint to check status.
Endpoint:
GET https://api.glossi.app/api/v1/jobs/{jobId}Headers:
| Header | Value |
|---|---|
X-API-Key | Your API key |
Response (in progress):
{
"jobId": "job-uuid",
"status": "PROCESSING",
"progress": {
"modelsUploaded": 2,
"modelsReady": 1,
"modelsTotal": 2,
"projectsCreated": 0,
"projectsTotal": 2,
"rendersComplete": 0,
"rendersTotal": 0
}
}Response (complete):
{
"jobId": "job-uuid",
"status": "COMPLETE",
"batchProject": {
"id": "batch-uuid",
"title": "API Job - 2025-02-10"
},
"progress": {
"modelsUploaded": 2,
"modelsReady": 2,
"modelsTotal": 2,
"projectsCreated": 2,
"projectsTotal": 2,
"rendersComplete": 0,
"rendersTotal": 0
},
"results": [
{
"model": { "id": "model-1-uuid", "name": "chair.glb" },
"project": { "id": "project-1-uuid", "name": "Chair Project" }
},
{
"model": { "id": "model-2-uuid", "name": "table.glb" },
"project": { "id": "project-2-uuid", "name": "Table Project" }
}
]
}Job Status Flow
AWAITING_UPLOADS → PROCESSING → CREATING_PROJECTS → RENDERING → COMPLETE
↓ ↓ ↓
FAILED FAILED FAILED| Status | Description |
|---|---|
AWAITING_UPLOADS | Waiting for files to be uploaded and confirmed |
PROCESSING | Models are being processed |
CREATING_PROJECTS | Projects are being created |
RENDERING | Renders in progress (if rendering requested) |
COMPLETE | All done |
FAILED | Something went wrong (check error field) |
Job Options
| Field | Type | Default | Description |
|---|---|---|---|
models | array | Required | Models to upload (fileName + fileType) |
templateId | string | - | Template to use for projects (required if rendering) |
createProjects | boolean | true | Create projects after models are ready |
renderSettings | object | - | Render settings. Include renderBookmarks: true or renderShots: true to trigger rendering |
webhookUrl | string | - | URL to receive completion notification |
Tip: To render images, include
"renderSettings": { "renderBookmarks": true }. To skip rendering, omitrenderSettingsentirely.
BatchProject
When you upload multiple models, they're automatically grouped into a BatchProject. The batchProject field in the response contains the ID you can use to manage them together.
Complete Example with cURL
# 1. Create job
JOB_RESPONSE=$(curl -s -X POST https://api.glossi.app/api/v1/jobs \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"models": [
{ "fileName": "chair.glb", "fileType": "glb" }
],
"templateId": "your-template-uuid",
"createProjects": true
}')
JOB_ID=$(echo $JOB_RESPONSE | jq -r '.jobId')
UPLOAD_URL=$(echo $JOB_RESPONSE | jq -r '.models[0].uploadUrl')
# 2. Upload file to S3
curl -X PUT "$UPLOAD_URL" \
-H "Content-Type: model/gltf-binary" \
--data-binary @chair.glb
# 3. Confirm uploads
curl -X POST "https://api.glossi.app/api/v1/jobs/$JOB_ID/confirm-uploads" \
-H "X-API-Key: $API_KEY"
# 4. Poll for completion
while true; do
STATUS_RESPONSE=$(curl -s "https://api.glossi.app/api/v1/jobs/$JOB_ID" \
-H "X-API-Key: $API_KEY")
STATUS=$(echo $STATUS_RESPONSE | jq -r '.status')
echo "Status: $STATUS"
if [ "$STATUS" = "COMPLETE" ] || [ "$STATUS" = "FAILED" ]; then
echo "Final response:"
echo $STATUS_RESPONSE | jq
break
fi
sleep 5
doneUsing Webhooks with Jobs
Instead of polling, you can provide a webhookUrl when creating the job to receive notifications:
{
"models": [
{ "fileName": "chair.glb", "fileType": "glb" }
],
"templateId": "your-template-uuid",
"webhookUrl": "https://your-app.com/webhooks/glossi"
}When the job completes (or fails), Glossi will POST to your webhook URL. See Webhooks for details on payload formats and signature verification.