{"openapi":"3.0.0","info":{"title":"PAYKX Rail Verification API","description":"Deterministic certainty layer for high-friction payment corridors.\n\nAll responses in **shadow/demo mode** are simulated. An issued API key is required to call protected endpoints.\n\n**Contact:** taseenrayed@paykx.co.uk","version":"1.2","contact":{"name":"Rayed, Founder","email":"taseenrayed@paykx.co.uk"},"license":{"name":"Private, For Partners and Investors Only"}},"servers":[{"url":"/","description":"Current environment (shadow/demo mode)"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"Issued API key provided after access approval."}},"schemas":{"VerifyRequest":{"type":"object","required":["corridor"],"properties":{"corridor":{"type":"string","example":"UK-NIGERIA","description":"Payment corridor in FROM-TO format (e.g. UK-NIGERIA, US-UK)"},"idempotency_key":{"type":"string","example":"a3f1c2e4-5b6d-4f7a-8c9e-0d1f2a3b4c5d","description":"Optional. A unique key (e.g. a UUID) supplied by the caller. The first request with a given key is processed normally and its result is cached; any later request reusing the same key with the SAME request body returns the identical cached result with idempotency_hit: true. Reusing the same key with a DIFFERENT request body returns 409 Conflict. Scoped per API key, so keys never collide across callers. Use this to make agentic retries safe."}}},"VerifyResponse":{"type":"object","properties":{"decision":{"type":"string","example":"GO","description":"GO / DEGRADED / NO-GO"},"score":{"type":"number","example":0.87,"description":"Composite risk score 0.0–1.0. Drives the decision band directly."},"confidence":{"type":"number","example":0.97,"description":"Engine certainty about its own assessment — independent of the score. High confidence + high score = clearly healthy. High confidence + low score = clearly risky. Low confidence = thin data, be cautious regardless of score."},"recommended_partner":{"type":"string","nullable":true,"example":"Partner A","description":"Highest-scored available partner for this corridor and decision. null for NO-GO or unsupported corridors."},"reasons":{"type":"array","description":"Structured reason objects. code is stable (use for logic); message is human-readable (may change).","items":{"type":"object","properties":{"code":{"type":"string","example":"HEALTHY_PARTNER"},"message":{"type":"string","example":"All monitored execution signals are healthy."}}},"example":[{"code":"HEALTHY_PARTNER","message":"All monitored execution signals are healthy."}]},"reason_codes":{"type":"array","items":{"type":"string"},"example":["HEALTHY_PARTNER"],"description":"Flat list of reason codes. Backward-compatible — prefer reasons for new integrations."},"request_id":{"type":"string","example":"req_m3a7fzk2p1r4","description":"Unique ID for this request. Include in support queries and log correlation."},"evaluated_at":{"type":"string","format":"date-time","example":"2026-07-15T11:30:47Z","description":"ISO 8601 timestamp of when the decision was computed. Use for audit trails and replay investigations."},"decision_model":{"type":"string","example":"v1.2","description":"Version of the Assessment Engine that produced this result. Useful when comparing historical replay results after model updates."},"correlation_id":{"type":"string","example":"pay_01J8X...","description":"Echoed back from your request if you supplied a correlation_id. Use to link a PAYKX decision to a specific payment execution in your system."},"volatility":{"type":"number","example":0.09,"description":"Standard deviation of recent corridor scores"},"probe_count":{"type":"integer","example":7,"description":"Number of signals evaluated"},"corridor_supported":{"type":"boolean","example":true,"description":"True only for fully validated corridors (GB-NG, NG-GB)."},"validation_note":{"type":"string","example":"Corridor fully validated with deep data.","description":"Human-readable note on corridor validation status."},"idempotency_hit":{"type":"boolean","example":false,"description":"True when replayed from a cached idempotency_key result."},"response_ms":{"type":"integer","example":112,"description":"Probe latency in milliseconds"},"signals":{"type":"object","description":"Clean summary of the seven signals.","example":{"balance_sufficient":true,"operation_valid":true,"network_healthy":true,"historical_failure_rate":0.04,"cop_overridden":false,"fx_volatility":"low","fraud_flags":0}},"probe_details":{"type":"object","description":"Per-signal breakdown: signal (CLEAR/LOW/MODERATE/ELEVATED/CRITICAL) and risk_value (0.0–1.0).","example":{"balance_sufficient":{"signal":"CLEAR","risk_value":1},"operation_valid":{"signal":"CLEAR","risk_value":0.95}}},"currency":{"type":"string","example":"GBP","description":"Corridor settlement currency"},"environment":{"type":"string","example":"fca-sandbox-validated"}}},"HealthResponse":{"type":"object","properties":{"status":{"type":"string","example":"healthy"},"version":{"type":"string","example":"1.2"},"timestamp":{"type":"string","format":"date-time"},"message":{"type":"string","example":"PAYKX Rail Verification API is running successfully"},"mode":{"type":"string","example":"shadow"},"environment":{"type":"string","example":"shadow-demo"}}}}},"paths":{"/api/v1/verify":{"post":{"summary":"Verify a payment corridor","description":"Runs a deterministic risk assessment using seven weighted signals: **fraud_flags** (30%), **network_healthy** (25%), **balance_sufficient** (15%), **fx_volatility** (10%), **operation_valid** (10%), **historical_failure_rate** (5%), **cop_overridden** (5%).\n\n- Score **≥ 0.80** → GO\n- Score **0.48–0.79** → DEGRADED\n- Score **< 0.48** → NO-GO\n\n**Corridor support:** Only **GB-NG** and **NG-GB** are fully validated with deep data. Any other corridor (other cross-border pairs, domestic, or crypto-to-fiat) returns `corridor_supported: false`, a `validation_note`, and a **DEGRADED** decision rather than a confident result.\n\nAdd `?mode=shadow` (default) for demo mode.","operationId":"verifyCorridorV1","security":[{"BearerAuth":[]}],"parameters":[{"name":"mode","in":"query","required":false,"schema":{"type":"string","enum":["shadow","live"],"default":"shadow"},"description":"Execution mode. Always use `shadow` in demo."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyRequest"},"examples":{"UK-Nigeria":{"summary":"UK → Nigeria corridor","value":{"corridor":"UK-NIGERIA"}},"US-UK":{"summary":"US → UK corridor","value":{"corridor":"US-UK"}}}}}},"responses":{"200":{"description":"Verification result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyResponse"},"example":{"decision":"GO","score":0.87,"volatility":0.09,"confidence":0.87,"probe_count":7,"corridor_supported":true,"validation_note":"Corridor fully validated with deep data.","response_ms":112,"signals":{"balance_sufficient":true,"operation_valid":true,"network_healthy":true,"historical_failure_rate":0.04,"cop_overridden":false,"fx_volatility":"low","fraud_flags":0},"probe_details":{"balance_sufficient":{"signal":"CLEAR","risk_value":1},"operation_valid":{"signal":"CLEAR","risk_value":0.95},"network_healthy":{"signal":"CLEAR","risk_value":0.92},"historical_failure_rate":{"signal":"CLEAR","risk_value":0.96},"cop_overridden":{"signal":"CLEAR","risk_value":1},"fx_volatility":{"signal":"CLEAR","risk_value":0.88},"fraud_flags":{"signal":"CLEAR","risk_value":1}},"currency":"GBP","api_version":"1.2","timestamp":"2026-05-10T11:30:47.705Z","environment":"fca-sandbox-validated"}}}},"400":{"description":"Invalid request body"},"401":{"description":"Missing or invalid API key"}}}},"/api/v1/batch-assess":{"post":{"summary":"Batch shadow audit","description":"Assesses up to **500 transactions** in a single request using the same seven-signal Assessment Engine as `/api/v1/verify`. Useful for retrospective analysis, model validation, and ops review without calling the API per-transaction.\n\n**Input formats:**\n- `application/json` — `{ \"transactions\": [...] }` array\n- `text/csv` — CSV body with a header row; required column: `corridor`; optional: `id`, `amount`, `currency`, `actual_outcome`, `timestamp`, `rail`\n\n**Output:** JSON report with per-row assessments plus summary statistics. Append `?format=csv` to get CSV output instead.\n\n**Summary fields:**\n- `total_assessed` — number of rows processed\n- `go / degraded / no_go` — verdict counts\n- `alignment_pct` — % of rows where PAYKX verdict matches the `actual_outcome` (only calculated for rows that provide an outcome)\n- `flagged_pre_failure` — rows where PAYKX raised DEGRADED or NO-GO and the actual outcome was FAILED or REJECTED (true positives)\n\nRequires the same Bearer/X-Api-Key authentication as `/api/v1/verify`.","operationId":"batchAssess","security":[{"BearerAuth":[]}],"parameters":[{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["csv"]},"description":"Set to `csv` to receive the response as a downloadable CSV file instead of JSON."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["transactions"],"properties":{"report_name":{"type":"string","example":"July shadow audit","description":"Optional label included in the report."},"transactions":{"type":"array","minItems":1,"maxItems":500,"items":{"type":"object","required":["corridor"],"properties":{"id":{"type":"string","example":"TXN-001","description":"Your transaction identifier. Auto-assigned if omitted."},"corridor":{"type":"string","example":"GB-NG","description":"ISO country-pair code."},"amount":{"type":"number","example":5000,"description":"Transfer amount in the source currency."},"currency":{"type":"string","example":"GBP","description":"ISO 4217 source currency code."},"actual_outcome":{"type":"string","example":"COMPLETED","enum":["COMPLETED","FAILED","DELAYED","REJECTED","PENDING"],"description":"Historical outcome. Supply this to enable alignment and flagged_pre_failure statistics."},"timestamp":{"type":"string","example":"2026-06-01T12:00:00Z"},"rail":{"type":"string","example":"SWIFT"}}}}}},"example":{"report_name":"July shadow audit","transactions":[{"id":"TXN-001","corridor":"GB-NG","amount":4500,"currency":"GBP","actual_outcome":"COMPLETED"},{"id":"TXN-002","corridor":"GB-NG","amount":85000,"currency":"GBP","actual_outcome":"FAILED"},{"id":"TXN-003","corridor":"NG-GB","amount":2200,"currency":"NGN","actual_outcome":"COMPLETED"}]}},"text/csv":{"schema":{"type":"string"},"example":"id,corridor,amount,currency,actual_outcome\nTXN-001,GB-NG,4500,GBP,COMPLETED\nTXN-002,GB-NG,85000,GBP,FAILED"}}},"responses":{"200":{"description":"Batch report (JSON). Use ?format=csv for CSV output.","content":{"application/json":{"schema":{"type":"object","properties":{"report_id":{"type":"string","example":"rpt_m9k3z2"},"report_name":{"type":"string","example":"July shadow audit"},"generated_at":{"type":"string","format":"date-time"},"model_version":{"type":"string","example":"v1.2"},"mode":{"type":"string","example":"shadow-audit"},"transaction_count":{"type":"integer","example":5},"summary":{"type":"object","properties":{"total_assessed":{"type":"integer","example":5},"go":{"type":"integer","example":3},"degraded":{"type":"integer","example":1},"no_go":{"type":"integer","example":1},"go_pct":{"type":"number","example":60},"degraded_pct":{"type":"number","example":20},"no_go_pct":{"type":"number","example":20},"avg_score":{"type":"number","example":0.782},"avg_confidence":{"type":"number","example":0.93},"alignment_pct":{"type":"number","nullable":true,"example":80,"description":"% of rows with actual_outcome that PAYKX verdict correctly matched. null when no outcomes provided."},"flagged_pre_failure":{"type":"integer","example":2,"description":"Rows where PAYKX raised DEGRADED or NO-GO and actual_outcome was FAILED or REJECTED."},"improvement_opportunities":{"type":"integer","example":1},"transactions_with_outcome":{"type":"integer","example":4}}},"_links":{"type":"object","properties":{"csv":{"type":"string","example":"Re-run this request with ?format=csv to receive CSV output"}}},"assessments":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer"},"transaction_id":{"type":"string"},"corridor":{"type":"string"},"corridor_supported":{"type":"boolean"},"amount":{"type":"number"},"currency":{"type":"string"},"actual_outcome":{"type":"string","nullable":true},"paykx_decision":{"type":"string","enum":["GO","DEGRADED","NO-GO"]},"paykx_score":{"type":"number"},"paykx_confidence":{"type":"number"},"paykx_volatility":{"type":"number"},"policy_capped":{"type":"boolean"},"alignment":{"type":"boolean","nullable":true},"improvement_opportunity":{"type":"boolean"},"improvement_note":{"type":"string","nullable":true},"flags":{"type":"array","items":{"type":"string"}}}}}}}},"text/csv":{"schema":{"type":"string"},"description":"Returned when ?format=csv is appended."}}},"400":{"description":"Invalid request body or CSV format"},"401":{"description":"Missing or invalid API key"}}}},"/api/v1/demo-verify":{"post":{"summary":"Demo verification — no API key required","description":"Runs a deterministic synthetic seven-signal demonstration, not a live production assessment. No authentication needed. Submit synthetic inputs only: amounts and identifiers are not guaranteed to be masked.\n\nReturns **GO**, **DEGRADED**, or **NO-GO** with a heuristic score and confidence, semantic-state reason codes, and a signal breakdown. FCA Sandbox testing does not imply FCA endorsement or validation of scoring accuracy.\n\n**Try it:** change `amount` between `15000` (GO) and `85000` (DEGRADED) to see the decision shift.","operationId":"demoVerify","security":[],"tags":["Demo"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["corridor"],"properties":{"corridor":{"type":"string","example":"GB-NG","description":"Payment corridor in ISO country-pair format."},"amount":{"type":"number","example":15000,"description":"Transfer amount. Amounts above £50,000 trigger the policy cap and are more likely to return DEGRADED."},"currency":{"type":"string","example":"GBP","description":"ISO 4217 source currency."},"sender_account_type":{"type":"string","example":"business","description":"Account type: business or personal."},"purpose":{"type":"string","example":"supplier_payment","description":"Payment purpose code."}}},"examples":{"GO — small amount":{"summary":"Likely GO — £15,000 supplier payment","value":{"corridor":"GB-NG","amount":15000,"currency":"GBP","sender_account_type":"business","purpose":"supplier_payment"}},"DEGRADED — large amount":{"summary":"Likely DEGRADED — £85,000 crosses policy cap","value":{"corridor":"GB-NG","amount":85000,"currency":"GBP","sender_account_type":"business","purpose":"supplier_payment"}}}}}},"responses":{"200":{"description":"Verification result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyResponse"},"example":{"decision":"GO","score":0.92,"confidence":0.91,"suggested_path":"Partner A","reason_codes":[],"reasons":[],"request_id":"req_synthetic_example","evaluated_at":"2026-07-29T09:13:05Z","probe_count":7,"corridor":"GB-NG","currency":"GBP","decision_model":"v1.3-demo","scoring_framework_version":"demo-synthetic-v2","mode":"synthetic","environment":"synthetic-demo"}}}},"400":{"description":"Invalid request body"},"429":{"description":"Rate limit exceeded"}}}},"/api/v1/demo-compare":{"post":{"summary":"Demo profile comparison — no API key required","description":"Evaluates the same payment against up to three named risk profiles (conservative, balanced, optimise_speed) and returns a divergence summary. No authentication needed.\n\n**Try it:** use `amount: 85000` to see profiles diverge — conservative and balanced return DEGRADED, speed-optimised returns GO.\n\nFor production use, see `POST /api/v1/decision/compare` (requires Bearer token).","operationId":"demoCompare","security":[],"tags":["Demo"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["payment"],"properties":{"payment":{"type":"object","description":"Payment details to evaluate.","properties":{"corridor":{"type":"string","example":"GB-NG","description":"Payment corridor in ISO country-pair format."},"amount":{"type":"number","example":85000,"description":"Transfer amount. Try 15000 (all GO) vs 85000 (profiles diverge)."},"currency":{"type":"string","example":"GBP","description":"ISO 4217 source currency."},"destination_country":{"type":"string","example":"NG","description":"Alternative to corridor — ISO 3166-1 alpha-2."},"sender_country":{"type":"string","example":"GB","description":"Alternative to corridor — ISO 3166-1 alpha-2."}}},"profiles":{"type":"array","items":{"type":"string","enum":["conservative","balanced","optimise_speed"]},"example":["conservative","balanced","optimise_speed"],"description":"Profiles to compare. Defaults to all three if omitted."}}},"examples":{"Divergent — £85,000":{"summary":"Profiles diverge — conservative/balanced DEGRADED, speed-optimised GO","value":{"payment":{"corridor":"GB-NG","amount":85000,"currency":"GBP"},"profiles":["conservative","balanced","optimise_speed"]}},"Agreement — £15,000":{"summary":"All three profiles agree — GO","value":{"payment":{"corridor":"GB-NG","amount":15000,"currency":"GBP"},"profiles":["conservative","balanced","optimise_speed"]}}}}}},"responses":{"200":{"description":"Profile comparison result","content":{"application/json":{"example":{"corridor":"GB-NG","amount":85000,"currency":"GBP","profiles_compared":["conservative","balanced","optimise_speed"],"results":{"conservative":{"decision":"DEGRADED","score":0.726,"go_threshold":0.85,"recheck_required":true,"profile_label":"Conservative — higher GO bar, shorter decision window","recommended_action":"Hold for manual review or re-verify with live probe."},"balanced":{"decision":"DEGRADED","score":0.726,"go_threshold":0.8,"recheck_required":true,"profile_label":"Balanced — PAYKX default","recommended_action":"Hold for manual review or re-verify with live probe."},"optimise_speed":{"decision":"GO","score":0.726,"go_threshold":0.7,"valid_for_seconds":600,"recheck_required":false,"profile_label":"Speed-optimised — lower GO bar, longer decision window","recommended_action":"Proceed with execution."}},"divergence":{"profiles_agree":false,"summary":"Profiles diverge: conservative→DEGRADED, balanced→DEGRADED, optimise_speed→GO. Review which profile matches your risk appetite."},"evaluated_at":"2026-07-29T12:00:00Z","model_version":"PAYKX-v1.3.0","environment":"sandbox"}}}},"400":{"description":"Invalid request body"},"429":{"description":"Rate limit exceeded"}}}},"/api/v1/decision/compare":{"post":{"summary":"Compare multiple partners on a corridor","description":"Ranks two or more payment partners against each other for a given corridor and amount. Each partner is scored independently using the same seven-signal engine.\n\nReturns partners in ranked order (best first) with individual decisions, scores, and a `recommended_action` per partner. Use this to route to the safest available partner at the time of execution.\n\n**Why it exists:** your orchestration layer decides which rail to use — this endpoint decides which partners are safe to route through at all.","operationId":"comparePartners","security":[{"BearerAuth":[]}],"tags":["Decisions"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["corridor","partners"],"properties":{"corridor":{"type":"string","example":"GB-NG","description":"Payment corridor in ISO country-pair format."},"amount":{"type":"number","example":15000,"description":"Transfer amount in source currency."},"currency":{"type":"string","example":"GBP","description":"ISO 4217 source currency."},"partners":{"type":"array","items":{"type":"string"},"example":["Partner A","Partner B","Partner C"],"description":"List of partner names to compare. Minimum 2."}}},"example":{"corridor":"GB-NG","amount":15000,"currency":"GBP","partners":["Partner A","Partner B","Partner C"]}}}},"responses":{"200":{"description":"Ranked partner list","content":{"application/json":{"example":{"corridor":"GB-NG","amount":15000,"currency":"GBP","recommended_partner":"Partner A","partner_count":3,"evaluated_at":"2026-07-29T09:15:00Z","ranked_partners":[{"rank":1,"partner":"Partner A","decision":"GO","score":0.91,"recommended_action":"Proceed"},{"rank":2,"partner":"Partner B","decision":"DEGRADED","score":0.74,"recommended_action":"Proceed with caution"},{"rank":3,"partner":"Partner C","decision":"NO-GO","score":0.38,"recommended_action":"Do not send"}]}}}},"400":{"description":"Invalid request body"},"401":{"description":"Missing or invalid API key"}}}},"/api/v1/audit/{request_id}":{"get":{"summary":"Retrieve the full audit record for a decision","description":"Returns the complete audit trail for a previous verification — all seven signal scores, the final decision, timestamp, and any human override applied.\n\n**Why it exists:** every decision PAYKX makes is stored as a structured, queryable record. If a regulator or compliance team asks why a payment was approved or blocked at a specific time, you pull this record and show them exactly what the engine knew at that moment.\n\nThe `request_id` comes from the `request_id` field of any `/api/v1/verify` or `/api/v1/demo-verify` response.","operationId":"getAuditRecord","security":[{"BearerAuth":[]}],"tags":["Audit"],"parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","example":"PAYKX-2026-1042"},"description":"The request_id returned by a previous verify call."}],"responses":{"200":{"description":"Full audit record with signal breakdown","content":{"application/json":{"example":{"request_id":"PAYKX-2026-1042","decision":"GO","score":0.91,"corridor":"GB-NG","amount":15000,"currency":"GBP","evaluated_at":"2026-07-29T09:13:05Z","human_override":null,"signal_contributions":[{"signal":"balance_sufficient","status":"CLEAR","risk_value":0.94},{"signal":"operation_valid","status":"CLEAR","risk_value":0.95},{"signal":"network_healthy","status":"CLEAR","risk_value":0.85},{"signal":"historical_failure_rate","status":"CLEAR","risk_value":0.96},{"signal":"cop_overridden","status":"CLEAR","risk_value":1},{"signal":"fx_volatility","status":"LOW","risk_value":0.83},{"signal":"fraud_flags","status":"CLEAR","risk_value":0.95}]}}}},"401":{"description":"Missing or invalid API key"},"404":{"description":"Request ID not found"}}}},"/api/health":{"get":{"summary":"API Health Check","description":"Returns the current health status of the PAYKX Rail API, including version and total verification count.","operationId":"getHealth","security":[],"responses":{"200":{"description":"API is healthy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"},"example":{"status":"healthy","version":"1.2","timestamp":"2026-05-10T11:30:46.379Z","total_verifications":43,"message":"PAYKX Rail Verification API is running successfully","mode":"shadow","environment":"shadow-demo"}}}}}}}}}