ZENETICS API
Jobs API (async jobs)

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:

  1. Queued - The job is waiting to be processed
  2. Running - The job is actively being executed
  3. Completed - The job finished successfully with results available
  4. Failed - The job encountered an error during processing
  5. Cancelled - The job was manually cancelled before completion
  6. 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.

HeaderTypeRequiredDescriptionExample Value
AuthorizationstringYesYour ZENETICS API key with Bearer prefixBearer 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

ParameterTypeRequiredDescriptionExample Values
pageintegerNoPage number (default: 1)1, 2, 3
page_sizeintegerNoJobs per page (default: 50, max: 100)25, 50, 100
statusarray[string]NoFilter by job status (can repeat parameter)queued, running, completed
typearray[string]NoFilter by job type (can repeat parameter)guard, test_runner
created_afterstring (ISO8601)NoJobs created after this timestamp2025-06-01T00:00:00Z
created_beforestring (ISO8601)NoJobs created before this timestamp2025-06-02T23:59:59Z
external_idstringNoFilter by your external reference IDcustomer-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

ParameterTypeRequiredDescriptionExample Value
job_idstringYesUnique identifier for the jobjob_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

  1. Use appropriate polling intervals: Poll jobs every 5-10 seconds for short operations, or every 30-60 seconds for long-running processes
  2. Implement timeout handling: Set reasonable timeouts for job completion to avoid infinite polling
  3. Handle all job statuses: Build logic to handle completed, failed, cancelled, and timeout statuses appropriately
  4. Use webhooks for efficiency: Configure webhooks instead of polling when possible to reduce API calls
  5. Filter jobs effectively: Use filtering parameters to reduce response sizes and improve performance
  6. Monitor progress data versions: Check the progress version field to ensure your client can handle the data format
  7. Store job IDs: Persist job IDs in your application to allow users to check status later
  8. Handle rate limits: Implement exponential backoff when you encounter rate limit responses
  9. Use external IDs: Include external reference IDs in job metadata to correlate with your application's data