ZENETICS API - Jobs Management
About Jobs in ZENETICS
ZENETICS processes many operations asynchronously to ensure optimal performance and reliability. When you submit requests for guard evaluations or test runs, these operations are queued as jobs and processed in the background. This approach allows ZENETICS to handle complex evaluations that may take several minutes while keeping your application responsive.
Jobs provide a complete audit trail of all processing activities in your ZENETICS account, including execution status, progress tracking, results, and detailed error information when issues occur. This transparency helps teams monitor their AI quality processes and troubleshoot issues effectively.
How Jobs Work
When you submit a request to ZENETICS (such as a guard evaluation), the system immediately returns a job reference that you can use to track the operation's progress. Jobs progress through several states:
- Queued - The job is waiting to be processed
- Running - The job is actively being executed
- Completed - The job finished successfully with results available
- Failed - The job encountered an error during processing
- Cancelled - The job was manually cancelled before completion
- Timeout - The job exceeded its maximum execution time
Each job includes versioned progress information that provides real-time updates about the current processing state. This allows you to build responsive user interfaces that keep users informed about long-running operations.
Integration Patterns
You can integrate jobs into your application using several patterns:
- Polling: Regularly check job status using the Jobs API
- Webhooks: Configure automatic notifications when jobs complete
- Real-time Updates: Build live progress indicators using the job progress data
Jobs API
The Jobs API allows you to query, monitor, and manage asynchronous operations in ZENETICS. This includes guard evaluations, test runs, and other background processes.
Authentication
Authentication is required using an API key provided in the request header.
Header | Type | Required | Description | Example Value |
---|---|---|---|---|
Authorization | string | Yes | Your ZENETICS API key with Bearer prefix | Bearer your-api-key |
List Jobs
Retrieve a paginated list of jobs with optional filtering and sorting.
Endpoint
GET https://api.zenetics.io/services/v1/jobs
Query Parameters
Parameter | Type | Required | Description | Example Values |
---|---|---|---|---|
page | integer | No | Page number (default: 1) | 1, 2, 3 |
page_size | integer | No | Jobs per page (default: 50, max: 100) | 25, 50, 100 |
status | array[string] | No | Filter by job status (can repeat parameter) | queued, running, completed |
type | array[string] | No | Filter by job type (can repeat parameter) | guard, test_runner |
created_after | string (ISO8601) | No | Jobs created after this timestamp | 2025-06-01T00:00:00Z |
created_before | string (ISO8601) | No | Jobs created before this timestamp | 2025-06-02T23:59:59Z |
external_id | string | No | Filter by your external reference ID | customer-evaluation-123 |
Response
Status Code: 200 OK
{
"jobs": [
{
"application_id": 12345,
"id": "job_abc123def456",
"url": "https://api.zenetics.io/services/v1/jobs/job_abc123def456",
"type": "guard",
"status": "running",
"priority": "normal",
"created_at": "2025-06-04T10:30:00Z",
"updated_at": "2025-06-04T10:32:15Z",
"queued_at": "2025-06-04T10:30:01Z",
"started_at": "2025-06-04T10:31:30Z",
"completed_at": null,
"expires_at": "2025-06-11T10:30:00Z",
"result": null,
"error": null,
"webhook_delivery_status": "pending",
"metrics": {},
"metadata": {
"guard_group_id": "gg_safety_checks_v2",
"external_id": "customer-evaluation-123"
}
}
],
"total_count": 147,
"page": 1,
"page_size": 50,
"has_next": true,
"next_page_url": "https://api.zenetics.io/services/v1/jobs?page=2&page_size=50"
}
Get Job Details
Retrieve detailed information about a specific job.
Endpoint
GET https://api.zenetics.io/services/v1/jobs/{job_id}
Path Parameters
Parameter | Type | Required | Description | Example Value |
---|---|---|---|---|
job_id | string | Yes | Unique identifier for the job | job_abc123def456 |
Response
Status Code: 200 OK
{
"application_id": 12345,
"id": "job_abc123def456",
"url": "https://api.zenetics.io/services/v1/jobs/job_abc123def456",
"type": "guard",
"status": "completed",
"priority": "normal",
"created_at": "2025-06-04T10:30:00Z",
"updated_at": "2025-06-04T10:35:22Z",
"queued_at": "2025-06-04T10:30:01Z",
"started_at": "2025-06-04T10:31:30Z",
"completed_at": "2025-06-04T10:35:22Z",
"expires_at": "2025-06-11T10:30:00Z",
"result": {
"result_id": "gr_xyz789abc123",
"result_url": "https://api.zenetics.io/services/v1/results/gr_xyz789abc123",
"result_type": "guard",
"expires_at": "2025-06-11T10:35:22Z"
},
"error": null,
"webhook_delivery_status": "delivered",
"metrics": {},
"metadata": {
"guard_group_id": "gg_safety_checks_v2",
"external_id": "customer-evaluation-123"
}
}
Error Responses
Job Not Found
Status Code: 404 Not Found
{
"error": "job_not_found",
"message": "Job with ID 'job_abc123def456' not found"
}
Invalid Job ID Format
Status Code: 400 Bad Request
{
"error": "validation_error",
"message": "Invalid job ID format",
"details": {
"field": "job_id",
"code": "invalid_format"
}
}
Authentication Error
Status Code: 401 Unauthorized
{
"error": "authentication_error",
"message": "Invalid or missing API key"
}
Rate Limit Exceeded
Status Code: 429 Too Many Requests
{
"error": "rate_limit_exceeded",
"message": "Rate limit exceeded. Try again in 60 seconds."
}
Example Requests
cURL - List Jobs
# Get all running jobs
curl -X GET "https://api.zenetics.io/services/v1/jobs?status=running" \
-H "Authorization: Bearer your-api-key-here"
# Get guard jobs from the last 24 hours
curl -X GET "https://api.zenetics.io/services/v1/jobs?type=guard&created_after=2025-06-03T10:30:00Z" \
-H "Authorization: Bearer your-api-key-here"
# Get paginated results
curl -X GET "https://api.zenetics.io/services/v1/jobs?page=2&page_size=25" \
-H "Authorization: Bearer your-api-key-here"
cURL - Get Job Details
curl -X GET "https://api.zenetics.io/services/v1/jobs/job_abc123def456" \
-H "Authorization: Bearer your-api-key-here"
JavaScript (fetch) - List Jobs
const response = await fetch(
'https://api.zenetics.io/services/v1/jobs?status=running&type=guard',
{
method: 'GET',
headers: {
Authorization: 'Bearer your-api-key-here',
},
}
);
const jobs = await response.json();
console.log(`Found ${jobs.total_count} jobs`);
// Process each job
jobs.jobs.forEach((job) => {
console.log(`Job ${job.id}: ${job.status}`);
if (job.progress && job.progress.data) {
const progress = job.progress.data;
console.log(
`Progress: ${progress.completed_guards}/${progress.total_guards} guards completed`
);
}
});
JavaScript (fetch) - Get Job Details
const jobId = 'job_abc123def456';
const response = await fetch(
`https://api.zenetics.io/services/v1/jobs/${jobId}`,
{
method: 'GET',
headers: {
Authorization: 'Bearer your-api-key-here',
},
}
);
const job = await response.json();
if (job.status === 'completed' && job.result) {
console.log(
`Job completed successfully. Results available at: ${job.result.result_url}`
);
} else if (job.status === 'failed' && job.error) {
console.error(`Job failed: ${job.error.error_message}`);
} else {
console.log(`Job is ${job.status}`);
}
Python (requests) - List Jobs with Filtering
import requests
from datetime import datetime, timedelta
# Get jobs from the last hour that are either running or completed
one_hour_ago = (datetime.utcnow() - timedelta(hours=1)).isoformat() + 'Z'
params = {
'status': ['running', 'completed'],
'created_after': one_hour_ago,
'page_size': 100
}
response = requests.get(
'https://api.zenetics.io/services/v1/jobs',
params=params,
headers={'Authorization': 'Bearer your-api-key-here'}
)
jobs_data = response.json()
print(f"Found {jobs_data['total_count']} jobs")
for job in jobs_data['jobs']:
print(f"Job {job['id']}: {job['status']} ({job['type']})")
Python (requests) - Poll Job Until Completion
import requests
import time
def wait_for_job_completion(job_id, api_key, timeout_seconds=300):
"""Poll a job until it completes or times out."""
start_time = time.time()
headers = {'Authorization': f'Bearer {api_key}'}
while time.time() - start_time < timeout_seconds:
response = requests.get(
f'https://api.zenetics.io/services/v1/jobs/{job_id}',
headers=headers
)
job = response.json()
status = job['status']
print(f"Job {job_id} status: {status}")
# Show progress if available
if job.get('progress') and job['progress'].get('data'):
progress = job['progress']['data']
if 'completed_guards' in progress:
print(f" Progress: {progress['completed_guards']}/{progress['total_guards']} guards")
if status in ['completed', 'failed', 'cancelled', 'timeout']:
return job
time.sleep(5) # Poll every 5 seconds
raise TimeoutError(f"Job {job_id} did not complete within {timeout_seconds} seconds")
# Usage
job = wait_for_job_completion('job_abc123def456', 'your-api-key-here')
if job['status'] == 'completed':
print(f"Job completed successfully! Results: {job['result']['result_url']}")
else:
print(f"Job ended with status: {job['status']}")
Best Practices
- Use appropriate polling intervals: Poll jobs every 5-10 seconds for short operations, or every 30-60 seconds for long-running processes
- Implement timeout handling: Set reasonable timeouts for job completion to avoid infinite polling
- Handle all job statuses: Build logic to handle completed, failed, cancelled, and timeout statuses appropriately
- Use webhooks for efficiency: Configure webhooks instead of polling when possible to reduce API calls
- Filter jobs effectively: Use filtering parameters to reduce response sizes and improve performance
- Monitor progress data versions: Check the progress version field to ensure your client can handle the data format
- Store job IDs: Persist job IDs in your application to allow users to check status later
- Handle rate limits: Implement exponential backoff when you encounter rate limit responses
- Use external IDs: Include external reference IDs in job metadata to correlate with your application's data