POST /scenarios
POST /api/v1/scenarios
Section titled “POST /api/v1/scenarios”Create a new servicing scenario.
Overview
Section titled “Overview”Creates a new scenario with applicant details, properties, loans, income, and expenses. All fields are optional - sensible defaults are applied if not provided.
Authentication
Section titled “Authentication”Required: RSA signature-based authentication
X-Auth-Client-ID: {clientId}X-Auth-Access-Token: {accessToken}X-Auth-Timestamp: {timestamp}X-Auth-Nonce: {nonce}X-Auth-Signature: {signature}Request
Section titled “Request”Method: POST
URL: https://api.quickli.com/api/v1/scenarios
Headers:
X-Auth-Client-ID: {clientId}X-Auth-Access-Token: {accessToken}X-Auth-Timestamp: {timestamp}X-Auth-Nonce: {nonce}X-Auth-Signature: {signature}Content-Type: application/jsonBody:
| Field | Type | Required | Description |
|---|---|---|---|
teamId | string | No | Team ID to create scenario under (defaults to first team) |
scenario | object | No | Complete scenario structure (see scenario schema) |
description | string | No | Scenario title/description - used by brokers to identify scenarios on Quickli |
Response
Section titled “Response”Success Response (200 OK)
Section titled “Success Response (200 OK)”{ "data": { "id": "507f1f77bcf86cd799439011", "teamId": "507f191e810c19729de860ea", "description": "First home buyer scenario", "createdBy": "broker@example.com", "dateCreated": "2025-11-03T10:30:00.000Z", "lastEditedBy": "broker@example.com", "lastEditedOn": "2025-11-03T10:30:00.000Z", "scenario": { "households": [], "income": [], "securities": [], "home_loans": [], "liabilities": [], "living_expenses": [], "rental_income": [], "self_employed_income": [], "home_loan_security_links": [], "additional_info": { "useDependantAges": false } } }, "meta": { "timestamp": "2025-11-03T10:30:00.000Z", "version": "1.0.0" }}Error Responses
Section titled “Error Responses”401 Unauthorized
Section titled “401 Unauthorized”Invalid credentials.
403 Forbidden
Section titled “403 Forbidden”User doesn’t have access to the specified team.
{ "error": { "code": "FORBIDDEN", "message": "User does not have access to team: 507f191e810c19729de860ea", "timestamp": "2025-11-03T10:30:00.000Z" }}422 Validation Error
Section titled “422 Validation Error”Invalid request body.
{ "error": { "code": "VALIDATION_ERROR", "message": "Validation failed", "details": { "issues": [ { "path": [ "scenario", "households", 0, "postcode" ], "message": "Expected number, received string" } ] }, "timestamp": "2025-11-03T10:30:00.000Z" }}Code Examples
Section titled “Code Examples”# Minimal scenario (empty)# Note: You need to generate the signature for each requestcurl -X POST https://api.quickli.com/api/v1/scenarios \-H "X-Auth-Client-ID: {clientId}" \-H "X-Auth-Access-Token: {accessToken}" \-H "X-Auth-Timestamp: {timestamp}" \-H "X-Auth-Nonce: {nonce}" \-H "X-Auth-Signature: {signature}" \-H "Content-Type: application/json" \-d '{"description": "Empty scenario","scenario": {}}'
# With team IDcurl -X POST https://api.quickli.com/api/v1/scenarios \-H "X-Auth-Client-ID: {clientId}" \-H "X-Auth-Access-Token: {accessToken}" \-H "X-Auth-Timestamp: {timestamp}" \-H "X-Auth-Nonce: {nonce}" \-H "X-Auth-Signature: {signature}" \-H "Content-Type: application/json" \-d '{"teamId": "507f191e810c19729de860ea","description": "My scenario","scenario": {}}'import crypto from 'crypto';
interface CreateScenarioRequest { teamId?: string; scenario?: SaveableScenario; description?: string;}
function generateAuthHeaders(method: string, path: string, body: unknown) { const clientId = process.env.QUICKLI_CLIENT_ID!; const accessToken = process.env.QUICKLI_ACCESS_TOKEN!; const privateKey = process.env.QUICKLI_PRIVATE_KEY!;
const timestamp = new Date().toISOString(); const nonce = crypto.randomUUID();
let bodyString = ''; if (body && typeof body === 'object' && Object.keys(body).length > 0) { bodyString = JSON.stringify(body); }
const bodyHash = crypto.createHash('sha256').update(bodyString).digest('hex'); const canonicalRequest = `${method}\n${path}\n${timestamp}\n${nonce}\n${bodyHash}`;
const sign = crypto.createSign('RSA-SHA256'); sign.update(canonicalRequest); const signature = sign.sign(privateKey, 'base64');
return { 'X-Auth-Client-ID': clientId, 'X-Auth-Access-Token': accessToken, 'X-Auth-Timestamp': timestamp, 'X-Auth-Nonce': nonce, 'X-Auth-Signature': signature, 'Content-Type': 'application/json' };}
async function createScenario(request: CreateScenarioRequest) { const headers = generateAuthHeaders('POST', '/api/v1/scenarios', request);
const response = await fetch('https://api.quickli.com/api/v1/scenarios', { method: 'POST', headers, body: JSON.stringify(request) });
if (!response.ok) { const error = await response.json(); throw new Error(error.error.message); }
const result = await response.json(); return result.data;}
// Create minimal scenarioconst scenario = await createScenario({ description: 'First home buyer', scenario: { households: [{ id: 'h1', status: 'single', num_adults: 1, num_dependants: 0, postcode: 2000, shared_with_households: [] }], income: [{ id: 'i1', which_household: 0, name: 'Primary Job', payg: 95000, casual: 0, commission: 0, overtime: 0, bonus: 0, allowances: 0, superannuation_income: 0, centrelink: 0, child_support_received: 0, other_income: 0 }] }});
console.log('Created scenario:', scenario.id);Example Use Cases
Section titled “Example Use Cases”1. Create Empty Scenario
Section titled “1. Create Empty Scenario”This is the standard use case and mimics how we use this functionality internally at Quickli.
Start with defaults and fill in later:
{ "description": "New client scenario"}2. Complete Scenario
Section titled “2. Complete Scenario”Example use cases:
- Cloning scenarios for work shopping
- Providing templates scenarios
Provide full details upfront:
{ "description": "First home buyer - Sydney", "scenario": { "households": [ { "id": "h1", "status": "single", "num_adults": 1, "num_dependants": 0, "postcode": 2000, "shared_with_households": [] } ], "income": [ { "id": "i1", "which_household": 0, "name": "Employment", "payg": 95000, "casual": 0, "commission": 0, "overtime": 0, "bonus": 0, "allowances": 0, "superannuation_income": 0, "centrelink": 0, "child_support_received": 0, "other_income": 0 } ], "securities": [ { "id": "s1", "address": "10 Example St, Sydney NSW 2000", "postcode": "2000", "transaction_type": "purchasing", "applicant_ownership": [ 100 ], "value": 750000, "property_type": "unit", "property_purpose": "owner_occupied", "weekly_rental_income": 0, "monthly_rental_expense": 0 } ], "home_loans": [ { "id": "l1", "product_type": "variable_package", "existing_or_proposed": "proposed", "loan_type": "owner_occupied", "lvr": 80, "loan_amount": 600000, "term": 30, "interest_only_period": 0, "lvr_behavior": "use-input" } ], "liabilities": [], "living_expenses": [ { "id": "e1", "simple_basic_expense": 2500, "use_detailed_basic_expense": false, "primary_residence": 0, "phone_internet_media": 150, "food_and_groceries": 500, "transport": 200, "utilities": 200, "clothing": 100, "medical": 50, "education": 0, "childcare": 0, "insurance": 100, "recreation": 200 } ], "rental_income": [], "self_employed_income": [], "home_loan_security_links": [ { "home_loan_id": "l1", "security_id": "s1" } ], "additional_info": { "useDependantAges": false } }}3. Specify Team
Section titled “3. Specify Team”- The endpoint will default to using the first available team listed on the user’s
OrganisationifteamIdis not provided. - If you wish to use an alternative team, you can view the user’s accessible teams via the user endpoint
Create in specific team:
// Get available teams firstconst user = await getUser();const teamId = user.teams[0].id;
// Create in that teamconst scenario = await createScenario({ teamId: teamId, description: 'Scenario for Team Alpha', scenario: {}});teamIdis optional - defaults to first team in user’s organisationscenariois optional - defaults to standard Quickli default scenariodescriptionis optional - defaults to ‘New Scenario’- Scenario ID is auto-generated (MongoDB ObjectId)
createdByis set to authenticated user’s email- Timestamps are auto-generated
See Also
Section titled “See Also”- Scenario Schema - Complete schema reference
- GET /scenarios/[id] - Retrieve scenario
- PUT /scenarios/[id] - Update scenario
- POST /compute/[scenarioId] - Calculate servicing
Last updated: 2025-11-19