{"openapi":"3.1.0","info":{"title":"POST /api/v1/credit/scorecard-versions/{version_id}/preview","version":"1.0.0","description":"Test a version against a business"},"servers":[{"url":"https://api.ondayzero.com","description":"Production"}],"paths":{"/api/v1/credit/scorecard-versions/{version_id}/preview":{"post":{"tags":["credit"],"summary":"Test a version against a business","description":"Measures the business and returns exactly what an assessment would: per-criterion value, resolved threshold, pass, fail or unmeasured with the reason, the score, the grade and `required_failed`. Nothing is saved and no event is emitted. Works on any version, drafts included. `passed: null` is unmeasured, not failed. `decision` is always null.","operationId":"preview_scorecard_version","parameters":[{"name":"version_id","in":"path","required":true,"schema":{"type":"string","title":"Version Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-business-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Business-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScorecardPreviewRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope_ScorecardPreviewResponse_"}}}},"400":{"description":"Bad Request - Invalid input","content":{"application/json":{"example":{"error":"validation_error","message":"Validation failed: due_date: Input should be a valid date","errors":{"due_date":"Input should be a valid date"},"code":"GEN_002","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized - Missing or expired token, an MCP OAuth token used against the REST API, or no access to this business","content":{"application/json":{"example":{"error":"unauthorized","message":"Authentication required","code":"AUTH_001","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Insufficient permissions","content":{"application/json":{"example":{"error":"forbidden","message":"You don't have permission to access this resource","code":"AUTH_002","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not Found - Resource does not exist","content":{"application/json":{"example":{"error":"not_found","message":"Resource not found","code":"NOT_FOUND_001","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"validation_error","message":"Validation failed: amount: Input should be a valid integer","errors":{"amount":"Input should be a valid integer"},"code":"GEN_002","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"}}}}},"x-fastapi-operation-id":"preview_scorecard_version_api_v1_credit_scorecard_versions__version_id__preview_post"}}},"components":{"schemas":{"ManualCheckResult":{"properties":{"id":{"type":"string","title":"Id"},"label":{"type":"string","title":"Label"},"status":{"type":"string","title":"Status","description":"pending, attested (reviewed and satisfied), exception (reviewed, exception noted) or not_applicable.","default":"pending"},"applicable":{"type":"boolean","title":"Applicable","description":"False when the check's condition excludes this application.","default":true},"evidence_required":{"type":"boolean","title":"Evidence Required","default":false},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"attested_by":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Attested By"},"attested_by_user_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Attested By User Id"},"at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"At","description":"When it was attested."},"attachment_s3_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Attachment S3 Key"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes","description":"Guidance from the scorecard, not the reviewer."},"policy_reference":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Policy Reference"}},"type":"object","required":["id","label"],"title":"ManualCheckResult","description":"A manual check on an assessment: what was reviewed, by whom, and when.\n\nManual checks cover the policy items no data can measure. A person\nattests to them; they never set a decision and never move the score."},"ScorecardPreviewRequest":{"properties":{"business_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Business Id","description":"The business to measure. Defaults to the business in x-business-id. Must be one the caller can access."},"requested_limit_cents":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Requested Limit Cents","description":"The limit being applied for, in cents. Rules written as a multiple of the limit report unmeasured without it."},"requested_term_days":{"anyOf":[{"type":"integer","maximum":3650.0,"minimum":1.0},{"type":"null"}],"title":"Requested Term Days"},"as_of":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"As Of","description":"Measure as at this date. Defaults to today."},"segment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Segment","description":"Merchant segment, for threshold overrides."}},"additionalProperties":false,"type":"object","title":"ScorecardPreviewRequest","description":"Test a version against a real business. Nothing is saved."},"ScorecardPreviewResponse":{"properties":{"scorecard_version_id":{"type":"string","title":"Scorecard Version Id"},"version_number":{"type":"integer","title":"Version Number"},"business_id":{"type":"string","title":"Business Id"},"business_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Business Name"},"as_of":{"type":"string","format":"date","title":"As Of"},"requested_limit_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Requested Limit Cents"},"requested_term_days":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Requested Term Days"},"segment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Segment"},"criteria":{"items":{"$ref":"#/components/schemas/UnderwritingCriterionResult"},"type":"array","title":"Criteria"},"manual_checks":{"items":{"$ref":"#/components/schemas/ManualCheckResult"},"type":"array","title":"Manual Checks"},"score_bps":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Score Bps","description":"Null when no criterion counted toward the score."},"grade":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Grade"},"passed_count":{"type":"integer","title":"Passed Count","default":0},"failed_count":{"type":"integer","title":"Failed Count","default":0},"unmeasured_count":{"type":"integer","title":"Unmeasured Count","default":0},"not_applicable_count":{"type":"integer","title":"Not Applicable Count","default":0},"required_failed":{"items":{"type":"string"},"type":"array","title":"Required Failed"},"points_earned":{"type":"integer","title":"Points Earned","default":0},"points_available":{"type":"integer","title":"Points Available","default":0},"scoring":{"$ref":"#/components/schemas/ScoringPolicy"},"persisted":{"type":"boolean","title":"Persisted","description":"Always false for a preview.","default":false},"decision":{"type":"null","title":"Decision","description":"Always null. The lending decision is the partner's (D-37)."}},"type":"object","required":["scorecard_version_id","version_number","business_id","as_of"],"title":"ScorecardPreviewResponse","description":"What an assessment would return, without creating one."},"ScoringPolicy":{"properties":{"method":{"type":"string","title":"Method","description":"How `score_bps` is computed. One method exists today.","default":"weighted_pass_ratio"},"unmeasured_policy":{"type":"string","title":"Unmeasured Policy","description":"`exclude_from_denominator`: unmeasured criteria are left out of the score. `count_as_zero`: their weight counts as not earned.","default":"exclude_from_denominator"}},"type":"object","title":"ScoringPolicy"},"SuccessEnvelope_ScorecardPreviewResponse_":{"properties":{"success":{"type":"boolean","title":"Success","default":true},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message"},"code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"},"data":{"anyOf":[{"$ref":"#/components/schemas/ScorecardPreviewResponse"},{"type":"null"}]}},"additionalProperties":true,"type":"object","title":"SuccessEnvelope[ScorecardPreviewResponse]"},"UnderwritingCriterionResult":{"properties":{"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id","description":"The criterion's id on the scorecard. Null on older assessments."},"key":{"type":"string","title":"Key"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"},"value":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Value"},"threshold":{"anyOf":[{"type":"number"},{"items":{"type":"number"},"type":"array"},{"type":"null"}],"title":"Threshold","description":"The figure the value was compared against, resolved for this application: a scalar, or [low, high] for the `between` comparator. Null when it could not be resolved (for example the rule is a multiple of a requested limit that was not supplied)."},"comparator":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comparator"},"passed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Passed","description":"Null means the figure could not be measured yet — distinct from a failure, and calling for a different action."},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"},"unit":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Unit"},"weight":{"type":"integer","title":"Weight","default":1},"required":{"type":"boolean","title":"Required","description":"Whether the rule is required for this application.","default":false},"applicable":{"type":"boolean","title":"Applicable","description":"False when the rule's `applies_when` excludes this application; such a rule is not scored.","default":true},"unmeasured_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Unmeasured Reason","description":"Why `passed` is null: requested_limit_missing, no_measurer, insufficient_history, no_shopify_connection, not_applicable, … Null when the criterion was measured."},"threshold_basis":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Threshold Basis","description":"`absolute`, or `requested_limit` for a multiple of the limit."},"threshold_value":{"anyOf":[{"type":"number"},{"items":{"type":"number"},"type":"array"},{"type":"null"}],"title":"Threshold Value","description":"The threshold as written on the scorecard, before resolution."},"required_when":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Required When","description":"The scorecard's `required` condition."},"applies_when":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Applies When","description":"The scorecard's `applies_when` condition."},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"},"policy_reference":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Policy Reference"},"evidence":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Evidence"}},"type":"object","required":["key"],"title":"UnderwritingCriterionResult","description":"One criterion, its value, its threshold, and where the figure came from.\n\nWe supply the assessment, not the verdict: thresholds and the lending\ndecision remain the partner's (§9.3)."},"ErrorResponse":{"title":"ErrorResponse","type":"object","description":"Envelope returned by every non-2xx response. Branch on `code` (stable) rather than `message` (human-readable, may change).","required":["error","message","code"],"properties":{"error":{"type":"string","description":"Error category: `validation_error`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `rate_limited`, `server_error`, or `service_unavailable`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to end users."},"code":{"type":"string","description":"Stable machine-readable code in `CATEGORY_NNN` form (e.g. `NOT_FOUND_006`, `AUTH_010`, `GEN_002`)."},"request_id":{"type":"string","description":"Correlation id for support requests. Echoes the `x-request-id` request header when one was supplied."},"errors":{"type":"object","additionalProperties":{"type":"string"},"description":"Field-level validation messages keyed by field name. Present on 400/422 validation failures only."}}}},"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Token","description":"API token authentication. Format: `Bearer dz_...`"}}},"security":[{"BearerAuth":[]}]}