The Analysis Jobs API provides asynchronous operations for validating and analyzing pricing configurations. Unlike the synchronous summary endpoint, these operations may take longer to complete as they involve constraint satisfaction programming (CSP) solvers.
Create Analysis Job
POST /api/v1/pricing/analysis
Creates and launches a new asynchronous analysis job. The job is processed in the background, and you can poll for results using the returned job ID.
Request
Content-Type : multipart/form-data
Parameters
The YAML file containing the pricing configuration to analyze.
The type of analysis operation to perform. Options:
validate - Verify pricing model coherence
optimal - Find optimal configurations (requires filters)
subscriptions - Enumerate all valid configurations
filter - Find configurations matching criteria (requires filters)
The constraint satisfaction solver to use. Options:
minizinc - MiniZinc solver (recommended)
choco - Choco solver (supports validate and subscriptions only)
JSON string containing filter criteria. Required for optimal and filter operations. Structure: {
"minPrice" : 0 ,
"maxPrice" : 100 ,
"maxSubscriptionSize" : 5 ,
"features" : [ "gitIntegration" , "prioritySupport" ],
"usageLimits" : [
{ "name" : "maxCollaboratorsPerProject" , "value" : 10 }
]
}
Optimization objective for optimal operations. Options:
minimize - Find lowest-cost configuration
maximize - Find highest-cost configuration
Example Requests
Validate Operation
Optimal Configuration
JavaScript
Python
curl -X POST "http://localhost:3000/api/v1/pricing/analysis" \
-F "[email protected] " \
-F "operation=validate" \
-F "solver=minizinc"
Response (202 Accepted)
Unique identifier for the created job. Use this to check status and retrieve results.
Initial status of the job. Always PENDING when first created.
ISO 8601 timestamp of when the job was submitted.
{
"jobId" : "job-a3f2b91c-4d8e-4b2a-9c1d-5e6f7a8b9c0d" ,
"status" : "PENDING" ,
"submittedAt" : "2026-03-05T14:23:45.123Z"
}
Get Job Status
GET /api/v1/pricing/analysis/{jobId}
Retrieve the current status and results (if completed) of an analysis job.
Request
The unique identifier returned when the job was created.
Example Request
curl "http://localhost:3000/api/v1/pricing/analysis/job-a3f2b91c-4d8e-4b2a-9c1d-5e6f7a8b9c0d"
Response
The response structure varies based on the job’s current status:
PENDING Status
{
"jobId" : "job-789" ,
"status" : "PENDING" ,
"submittedAt" : "2026-03-05T11:00:00Z"
}
RUNNING Status
{
"jobId" : "job-789" ,
"status" : "RUNNING" ,
"submittedAt" : "2026-03-05T11:00:00Z" ,
"startedAt" : "2026-03-05T11:00:05Z"
}
COMPLETED Status
ISO 8601 timestamp of job submission
ISO 8601 timestamp of when job processing started
ISO 8601 timestamp of when job completed
The analysis result. Structure depends on the operation type: For validate operation: For optimal operation: {
"optimal" : {
"subscriptions" : [
{
"plan" : "FREE" ,
"addOns" : [],
"features" : [ "latexEditor" , "realTimeCollaboration" ],
"usageLimits" : [{ "name" : "maxCollaboratorsPerProject" , "value" : 1 }],
"cost" : "0 USD"
}
],
"cost" : 0
}
}
See Optimization and Subscriptions for detailed result schemas.
FAILED Status
ISO 8601 timestamp of job submission
ISO 8601 timestamp of when job started (may be null if failed before starting)
ISO 8601 timestamp of when job failed
Error information Human-readable error message
Technical details or stack trace (optional)
{
"jobId" : "job-xyz" ,
"status" : "FAILED" ,
"submittedAt" : "2026-03-05T12:00:00Z" ,
"startedAt" : "2026-03-05T12:00:05Z" ,
"failedAt" : "2026-03-05T12:00:06Z" ,
"error" : {
"message" : "Solver timeout after 30s" ,
"details" : "MiniZinc solver exceeded maximum execution time"
}
}
Validation Operation
The validate operation verifies the mathematical and logical coherence of a pricing specification.
What Gets Validated
Ensures that plan prices are logically ordered and add-on prices are reasonable relative to plan prices.
Verifies that feature definitions are consistent across plans and that feature hierarchies make sense.
Validates that add-ons are only available for the plans they’re supposed to be available for.
Impossible Configurations
Detects configurations that cannot exist due to constraint conflicts.
Example Validation Request
curl -X POST "http://localhost:3000/api/v1/pricing/analysis" \
-F "[email protected] " \
-F "operation=validate" \
-F "solver=minizinc"
Response:
{
"jobId" : "job-validate-123" ,
"status" : "PENDING" ,
"submittedAt" : "2026-03-05T14:30:00Z"
}
After polling:
{
"jobId" : "job-validate-123" ,
"status" : "COMPLETED" ,
"submittedAt" : "2026-03-05T14:30:00Z" ,
"startedAt" : "2026-03-05T14:30:02Z" ,
"completedAt" : "2026-03-05T14:30:05Z" ,
"result" : {
"valid" : true
}
}
Invalid Pricing Model Example
If validation fails:
{
"jobId" : "job-validate-456" ,
"status" : "COMPLETED" ,
"submittedAt" : "2026-03-05T14:35:00Z" ,
"startedAt" : "2026-03-05T14:35:02Z" ,
"completedAt" : "2026-03-05T14:35:04Z" ,
"result" : {
"valid" : false ,
"error" : "No valid configurations exist: Add-on 'PREMIUM_SUPPORT' requires plan 'ENTERPRISE' which does not exist"
}
}
Polling Strategy
Since analysis jobs are asynchronous, you need to poll for results:
JavaScript Polling
Python Polling
async function waitForJob ( jobId , maxWaitMs = 60000 ) {
const startTime = Date . now ();
while ( Date . now () - startTime < maxWaitMs ) {
const response = await fetch (
`http://localhost:3000/api/v1/pricing/analysis/ ${ jobId } `
);
const job = await response . json ();
if ( job . status === 'COMPLETED' ) {
return job . result ;
}
if ( job . status === 'FAILED' ) {
throw new Error ( job . error . message );
}
// Wait 2 seconds before next poll
await new Promise ( resolve => setTimeout ( resolve , 2000 ));
}
throw new Error ( 'Job timeout' );
}
// Usage
const result = await waitForJob ( 'job-123' );
console . log ( 'Analysis complete:' , result );
Use exponential backoff for polling in production: start with 1s intervals and increase to 5s for long-running jobs.
Error Responses
400 Bad Request
{
"error" : "Missing required fields: operation and solver are required"
}
{
"error" : "Invalid filters format. Must be valid JSON."
}
404 Not Found
{
"error" : "Job not found"
}
500 Internal Server Error
{
"error" : "Internal server error during job submission" ,
"details" : "Failed to initialize MiniZinc solver"
}
Implementation
The analysis job endpoints are implemented in /home/daytona/workspace/source/analysis_api/src/api/analysis.ts:23 and :138.
Jobs are stored in-memory by default. For production use, implement persistent storage (Redis, database) to survive server restarts.
Optimization Find optimal configurations with custom criteria
Subscriptions Enumerate all valid subscription configurations