{"openapi":"3.1.0","info":{"title":"POST /api/v1/credit/underwriting/assessments/{assessment_id}/manual-checks/{check_id}","version":"1.0.0","description":"Attest a manual check"},"servers":[{"url":"https://api.ondayzero.com","description":"Production"}],"paths":{"/api/v1/credit/underwriting/assessments/{assessment_id}/manual-checks/{check_id}":{"post":{"tags":["credit"],"summary":"Attest a manual check","description":"Records a person's review of one of the scorecard's manual checks — the policy items no data can measure. `attested` means reviewed and satisfied; `exception` means reviewed with an exception noted; `pending` clears an earlier attestation. A check with `evidence_required` needs an `attachment_s3_key`. Manual checks are reported beside the score: they never change it and never set a decision.","operationId":"attest_manual_check","parameters":[{"name":"assessment_id","in":"path","required":true,"schema":{"type":"string","title":"Assessment Id"}},{"name":"check_id","in":"path","required":true,"schema":{"type":"string","title":"Check 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/ManualCheckAttestRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope_UnderwritingAssessmentResponse_"}}}},"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":"attest_manual_check_api_v1_credit_underwriting_assessments__assessment_id__manual_checks__check_id__post"}}},"components":{"schemas":{"AdverseActionReason":{"properties":{"criterion_key":{"type":"string","title":"Criterion Key"},"criterion_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Criterion Id"},"label":{"type":"string","title":"Label"},"measured":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Measured"},"threshold":{"anyOf":[{"type":"number"},{"items":{"type":"number"},"type":"array"},{"type":"null"}],"title":"Threshold"},"comparator":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comparator"},"direction":{"type":"string","title":"Direction","description":"below, above, not_equal, equal, or outside: where the figure fell."},"unit":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Unit"},"required":{"type":"boolean","title":"Required","default":false},"weight":{"type":"integer","title":"Weight","default":0},"contribution_bps":{"type":"integer","title":"Contribution Bps","description":"The criterion's weight over the points available.","default":0}},"type":"object","required":["criterion_key","label","direction"],"title":"AdverseActionReason","description":"A failed scorecard criterion, as a reason a lender could give."},"AssessmentStatusEnum":{"type":"string","enum":["pending","completed","failed"],"title":"AssessmentStatusEnum","description":"Underwriting assessment lifecycle.\n\nPlaid backfill, categorisation, and trailing-ratio history can take up\nto three days (FRD §9.3), so an assessment is explicitly asynchronous."},"ManualCheckAttestRequest":{"properties":{"status":{"type":"string","enum":["attested","exception","pending"],"title":"Status","description":"attested: reviewed and satisfied. exception: reviewed, with an exception noted. pending: clear an earlier attestation."},"note":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Note"},"attachment_s3_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Attachment S3 Key","description":"Required when the check has `evidence_required`."}},"additionalProperties":false,"type":"object","required":["status"],"title":"ManualCheckAttestRequest","description":"Record a person's review of one manual check."},"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."},"SuccessEnvelope_UnderwritingAssessmentResponse_":{"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/UnderwritingAssessmentResponse"},{"type":"null"}]}},"additionalProperties":true,"type":"object","title":"SuccessEnvelope[UnderwritingAssessmentResponse]"},"UnderwritingAssessmentResponse":{"properties":{"id":{"type":"string","title":"Id"},"credit_line_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Credit Line Id"},"external_application_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"External Application Id"},"status":{"$ref":"#/components/schemas/AssessmentStatusEnum"},"requested_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Requested At"},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Completed At"},"criteria":{"items":{"$ref":"#/components/schemas/UnderwritingCriterionResult"},"type":"array","title":"Criteria"},"financials":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Financials"},"failure_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Failure Reason"},"score_bps":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Score Bps","description":"Weighted points earned over points available across measured criteria, in basis points (D-38). Null until completed."},"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","description":"Criteria whose `applies_when` excluded this application.","default":0},"required_failed":{"items":{"type":"string"},"type":"array","title":"Required Failed"},"segment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Segment"},"scorecard_version_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scorecard Version Id","description":"The exact scorecard version the assessment ran against. Null for an ad-hoc `criteria_override`."},"scorecard_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scorecard Id"},"scorecard_version_number":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Scorecard Version Number"},"scorecard_source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scorecard Source","description":"version, override (criteria_override), or program (pre-versioning)."},"subject_business_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subject Business Id","description":"The business whose data was measured, when not the operator."},"requested_limit_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Requested Limit Cents"},"requested_term_days":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Requested Term Days"},"manual_checks":{"items":{"$ref":"#/components/schemas/ManualCheckResult"},"type":"array","title":"Manual Checks","description":"Reviewed by a person; reported beside the score, never in it."},"grade":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Grade","description":"From the scorecard's grade bands. Null when it has none."},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes","description":"Reviewer notes."},"adverse_action_reasons":{"items":{"$ref":"#/components/schemas/AdverseActionReason"},"type":"array","title":"Adverse Action Reasons","description":"The criteria that were measured and failed, required ones first, then by weight. Empty when nothing failed. Figures only: no notice is sent."},"waiting_on":{"items":{"type":"string"},"type":"array","title":"Waiting On","description":"While pending: the merchant data the nightly sweep is still waiting for before it measures (`bank_connection`, `bank_backfill`, `categorisation`, `shopify_sync`, and `shopify_disputes` when the scorecard has a chargeback rule and no finished sync has pulled the year of disputes yet). On a completed assessment: what was still missing when it completed (at the program's `underwriting_wait_days` deadline, or on an operator's run). Empty when nothing was missing or no check ran."},"ready_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Ready At","description":"When the merchant's data was first found complete, at the request or a nightly check. Null while waiting, or when the assessment completed without it."},"wait_deadline":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Wait Deadline","description":"When the sweep stops waiting and completes the assessment with whatever data exists: `requested_at` plus the program's `underwriting_wait_days`. Set when the assessment is requested."},"decision":{"type":"null","title":"Decision","description":"Always null. The lending decision is the partner's (§9.3, D-37)."}},"type":"object","required":["id","status"],"title":"UnderwritingAssessmentResponse","description":"Assessment evidence — criteria, values, thresholds, and sources."},"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":[]}]}