Response Schema Specification

Response Schema Specification

Overview

Spartera requires a standardized response format to ensure consistency across all models
in the marketplace. This page provides detailed specifications and examples for implementing
the required response schema.

Required Response Format

Structure

{
  "timestamp": "2026-01-30T19:30:00.000000+00:00",
  "answer_value": 123.45,
  "asset_id": "optional-identifier"
}

Field Specifications

1. timestamp (Required)

Type: String
Format: ISO-8601 with timezone (UTC recommended)
Purpose: Records when the prediction was generated

Valid Formats:

// ✅ Recommended (with microseconds and timezone)
"2026-01-30T19:30:00.000000+00:00"

// ✅ Acceptable (with timezone)
"2026-01-30T19:30:00+00:00"

// ✅ Acceptable (Z notation for UTC)
"2026-01-30T19:30:00.000000Z"

// ❌ Invalid (no timezone)
"2026-01-30T19:30:00"

// ❌ Invalid (wrong format)
"01/30/2026 7:30 PM"

Implementation Examples:

## Python
from datetime import datetime, timezone

timestamp = datetime.now(timezone.utc).isoformat()
## Output: "2026-01-30T19:30:00.123456+00:00"
// JavaScript/Node.js
const timestamp = new Date().toISOString();
// Output: "2026-01-30T19:30:00.123Z"
// Java
import java.time.Instant;

String timestamp = Instant.now().toString();
// Output: "2026-01-30T19:30:00.123456Z"
// Go
import "time"

timestamp := time.Now().UTC().Format(time.RFC3339Nano)
// Output: "2026-01-30T19:30:00.123456789Z"

2. answer_value (Required)

Type: Number (float or integer)
Purpose: The prediction result from your model

Valid Types:

// ✅ Float
"answer_value": 123.45

// ✅ Integer
"answer_value": 1

// ✅ Probability (0-1)
"answer_value": 0.87

// ✅ Percentage (0-100)
"answer_value": 87.5

// ✅ Negative numbers
"answer_value": -15.2

// ❌ Invalid (string)
"answer_value": "123.45"

// ❌ Invalid (boolean)
"answer_value": true

// ❌ Invalid (array)
"answer_value": [1, 2, 3]

// ❌ Invalid (object)
"answer_value": {"prediction": 123}

Use Cases by Model Type:

Model TypeExample ValueDescription
Binary Classification0 or 1Class label
Probability Score0.87Confidence (0-1)
Regression2450.75Predicted numeric value
Multi-class (Single)3Class index
Ranking Score87.5Relative score

Important Notes:

  • For multi-class classification, return a single class (highest probability)
  • For confidence scores, use 0-1 range (not percentages)
  • For currency, return raw numbers without formatting (use 2450.75, not "$2,450.75")
  • For percentages, decide on 0-1 or 0-100 and document clearly

3. asset_id (Optional)

Type: String or null
Purpose: Identifier for tracking and logging

// ✅ With asset_id (if provided in request)
"asset_id": "abc-123-def-456"

// ✅ Without asset_id
"asset_id": null

How to Handle:

## Extract from request header
asset_id = request.headers.get('X-Asset-ID')

## Return in response
return {
    'timestamp': timestamp,
    'answer_value': prediction,
    'asset_id': asset_id  # Will be None if header not present
}

When to Use:

  • Echo back the X-Asset-ID header value if provided
  • Set to null if no asset ID in request
  • Optionally use for internal logging/tracking

Complete Examples by Model Type

Binary Classification

Model: Fraud Detection
Prediction: Transaction is fraudulent (1) or legitimate (0)

{
  "timestamp": "2026-01-30T19:30:00.000000+00:00",
  "answer_value": 1,
  "asset_id": "fraud-check-tx-12345"
}

Probability Score

Model: Customer Churn Prediction
Prediction: 87% probability of churn

{
  "timestamp": "2026-01-30T19:30:00.000000+00:00",
  "answer_value": 0.87,
  "asset_id": "churn-customer-789"
}

Regression

Model: House Price Prediction
Prediction: $450,000

{
  "timestamp": "2026-01-30T19:30:00.000000+00:00",
  "answer_value": 450000.00,
  "asset_id": "property-valuation-456"
}

Multi-class Classification

Model: Sentiment Analysis
Prediction: Neutral (class 1, where 0=negative, 1=neutral, 2=positive)

{
  "timestamp": "2026-01-30T19:30:00.000000+00:00",
  "answer_value": 1,
  "asset_id": "sentiment-text-abc"
}

Ranking/Scoring

Model: Lead Qualification
Prediction: Lead score of 87.5 out of 100

{
  "timestamp": "2026-01-30T19:30:00.000000+00:00",
  "answer_value": 87.5,
  "asset_id": "lead-score-contact-999"
}

Error Response Format

While Spartera handles most errors, your API should return helpful error messages:

Standard Error Response

{
  "error": "Missing required parameter: age",
  "details": "The 'age' field is required for prediction",
  "error_code": "MISSING_PARAMETER"
}

Error Response Fields

FieldTypeRequiredDescription
errorString✅ YesShort error message
detailsStringRecommendedDetailed explanation
error_codeStringOptionalMachine-readable code

Common Error Responses

// Missing Parameter
{
  "error": "Missing required fields",
  "details": "Fields missing: age, income",
  "error_code": "MISSING_FIELDS"
}

// Invalid Value
{
  "error": "Invalid parameter value",
  "details": "Age must be between 18 and 100, got: 150",
  "error_code": "INVALID_VALUE"
}

// Model Failure
{
  "error": "Model prediction failed",
  "details": "Internal model error. Please try again.",
  "error_code": "MODEL_ERROR"
}

// Rate Limit
{
  "error": "Rate limit exceeded",
  "details": "Maximum 100 requests per minute. Try again in 30 seconds.",
  "error_code": "RATE_LIMIT_EXCEEDED"
}

Implementation Examples

Python (Flask)

from flask import Flask, request, jsonify
from datetime import datetime, timezone

app = Flask(__name__)

@app.route('/predict', methods=['POST'])
def predict():
    try:
        # Get input
        data = request.json
        
        # Validate (your logic)
        if 'age' not in data:
            return jsonify({
                'error': 'Missing required parameter: age'
            }), 400
        
        # Make prediction (your model)
        prediction = your_model.predict(data)
        
        # Extract asset_id
        asset_id = request.headers.get('X-Asset-ID')
        
        # Return Spartera format
        return jsonify({
            'timestamp': datetime.now(timezone.utc).isoformat(),
            'answer_value': float(prediction),
            'asset_id': asset_id
        }), 200
        
    except Exception as e:
        return jsonify({
            'error': str(e)
        }), 500

Node.js (Express)

const express = require('express');
const app = express();

app.use(express.json());

app.post('/predict', async (req, res) => {
    try {
        // Get input
        const data = req.body;
        
        // Validate
        if (!data.age) {
            return res.status(400).json({
                error: 'Missing required parameter: age'
            });
        }
        
        // Make prediction
        const prediction = await yourModel.predict(data);
        
        // Extract asset_id
        const assetId = req.headers['x-asset-id'] || null;
        
        // Return Spartera format
        res.json({
            timestamp: new Date().toISOString(),
            answer_value: prediction,
            asset_id: assetId
        });
        
    } catch (error) {
        res.status(500).json({
            error: error.message
        });
    }
});

Go

package main

import (
    "encoding/json"
    "net/http"
    "time"
)

type PredictionRequest struct {
    Age    int     `json:"age"`
    Income float64 `json:"income"`
}

type PredictionResponse struct {
    Timestamp   string  `json:"timestamp"`
    AnswerValue float64 `json:"answer_value"`
    AssetID     string  `json:"asset_id,omitempty"`
}

func predictHandler(w http.ResponseWriter, r *http.Request) {
    // Parse request
    var req PredictionRequest
    if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
        http.Error(w, "Invalid request", http.StatusBadRequest)
        return
    }
    
    // Make prediction
    prediction := yourModel.Predict(req)
    
    // Get asset_id
    assetID := r.Header.Get("X-Asset-ID")
    
    // Return response
    resp := PredictionResponse{
        Timestamp:   time.Now().UTC().Format(time.RFC3339Nano),
        AnswerValue: prediction,
        AssetID:     assetID,
    }
    
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(resp)
}

Validation Checklist

Before connecting to Spartera, verify your response:

  • Returns valid JSON
  • Contains all three required fields
  • timestamp is ISO-8601 format with timezone
  • answer_value is a number (not string)
  • asset_id is string or null (not missing)
  • HTTP status code is 200 for success
  • Error responses use appropriate status codes (400, 500, etc.)
  • Response headers include Content-Type: application/json

Common Mistakes

❌ Returning String Instead of Number

// Wrong
{
  "timestamp": "2026-01-30T19:30:00Z",
  "answer_value": "123.45",  // String!
  "asset_id": null
}

// Correct
{
  "timestamp": "2026-01-30T19:30:00Z",
  "answer_value": 123.45,  // Number
  "asset_id": null
}

❌ Missing Timezone

// Wrong
{
  "timestamp": "2026-01-30T19:30:00",  // No timezone!
  "answer_value": 123.45,
  "asset_id": null
}

// Correct
{
  "timestamp": "2026-01-30T19:30:00+00:00",  // Has timezone
  "answer_value": 123.45,
  "asset_id": null
}

❌ Omitting asset_id Field

// Wrong
{
  "timestamp": "2026-01-30T19:30:00Z",
  "answer_value": 123.45
  // Missing asset_id field entirely!
}

// Correct
{
  "timestamp": "2026-01-30T19:30:00Z",
  "answer_value": 123.45,
  "asset_id": null  // Include even if null
}

❌ Extra Fields

// Acceptable but not necessary
{
  "timestamp": "2026-01-30T19:30:00Z",
  "answer_value": 123.45,
  "asset_id": null,
  "confidence": 0.95,  // Extra field (ignored by Spartera)
  "model_version": "v2.1"  // Extra field (ignored by Spartera)
}

Note: Extra fields are ignored but won't cause errors. However, keep responses minimal for better performance.


Testing Your Response

Manual Test with cURL

curl -X POST https://your-api.com/predict \
  -H "X-API-Key: your-key" \
  -H "Content-Type: application/json" \
  -d '{"age": 35, "income": 75000}' \
  | python -m json.tool

Expected output:

{
  "timestamp": "2026-01-30T19:30:00.123456+00:00",
  "answer_value": 0.87,
  "asset_id": null
}

Automated Validation

import requests
import json
from datetime import datetime

def validate_response(url, api_key, payload):
    headers = {
        'X-API-Key': api_key,
        'Content-Type': 'application/json'
    }
    
    response = requests.post(url, json=payload, headers=headers)
    
    # Check status code
    assert response.status_code == 200, f"Expected 200, got {response.status_code}"
    
    # Parse JSON
    data = response.json()
    
    # Check required fields
    assert 'timestamp' in data, "Missing timestamp"
    assert 'answer_value' in data, "Missing answer_value"
    assert 'asset_id' in data, "Missing asset_id"
    
    # Check types
    assert isinstance(data['timestamp'], str), "timestamp must be string"
    assert isinstance(data['answer_value'], (int, float)), "answer_value must be number"
    
    # Validate timestamp format
    datetime.fromisoformat(data['timestamp'].replace('Z', '+00:00'))
    
    print("✅ Response format valid!")
    return data

## Test
result = validate_response(
    'https://your-api.com/predict',
    'your-key',
    {'age': 35, 'income': 75000}
)

Next Steps: