{
 "openapi": "3.1.0",
 "info": {
  "title": "nsgoods Sanctions Screening",
  "version": "1.0.0",
  "description": "Screen a crypto wallet address, or the payee of any x402 endpoint, against the OFAC SDN, UN, EU and UK (HMT) sanctions lists. Each list is reported separately with its own version date, inside an EIP-191 signed response (signer 0x57fF0F084Cba33e6761503f90eEF0Da9F159350c). Paid over x402, 0.01 USDC on Base or Solana, no account. Free signed preview on each path.",
  "contact": {
   "name": "nsgoods",
   "email": "nikos@nsgoods.org",
   "url": "https://x402.nsgoods.org"
  },
  "license": {
   "name": "Proprietary"
  }
 },
 "servers": [
  {
   "url": "https://sanctions.nsgoods.org"
  }
 ],
 "paths": {
  "/screen-multi": {
   "get": {
    "operationId": "screenMulti",
    "summary": "Screen one wallet address against OFAC, UN, EU and UK lists",
    "parameters": [
     {
      "name": "address",
      "in": "query",
      "required": true,
      "schema": {
       "type": "string"
      },
      "description": "Raw blockchain address. EVM 0x-hex, or base58/bech32 for BTC, SOL, TRX and similar"
     },
     {
      "name": "chain",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      },
      "description": "Optional chain hint; advisory only, matching is global by address value"
     },
     {
      "name": "request_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string",
       "maxLength": 128,
       "pattern": "^[A-Za-z0-9._:-]+$"
      },
      "description": "Optional id echoed inside the signed body"
     }
    ],
    "responses": {
     "200": {
      "description": "Signed result",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ScreenResult"
        }
       }
      }
     },
     "400": {
      "description": "Input is not a recognised crypto address (for /screen-url not an https URL). Returned BEFORE the payment gate; not charged. An empty or absent address/url returns the normal 402, as x402 discovery requires.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/InvalidInput"
        }
       }
      }
     },
     "402": {
      "description": "Payment required (x402). Terms also in the PAYMENT-REQUIRED response header.",
      "headers": {
       "PAYMENT-REQUIRED": {
        "schema": {
         "type": "string"
        },
        "description": "Base64 x402 payment requirements"
       }
      },
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/PaymentRequired"
        }
       }
      }
     }
    },
    "x-402": {
     "scheme": "exact",
     "price": "0.01 USDC per call",
     "version": 2,
     "accepts": [
      {
       "scheme": "exact",
       "network": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
       "asset": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
       "amount": "10000",
       "payTo": "35tCuyL3E7M88jfhTeEaRxhrbuKFyQLWgxJQyf5QcLLe",
       "maxTimeoutSeconds": 300,
       "extra": {
        "feePayer": "D6ZhtNQ5nT9ZnTHUbqXZsTx5MH2rPFiBBggX4hY1WePM"
       },
       "maxAmountRequired": "10000"
      },
      {
       "scheme": "exact",
       "network": "eip155:8453",
       "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
       "amount": "10000",
       "payTo": "0xc87a06DEE4c0E85912296002617120BBfd5EF990",
       "maxTimeoutSeconds": 300,
       "extra": {
        "name": "USD Coin",
        "version": "2"
       },
       "maxAmountRequired": "10000"
      }
     ],
     "note": "Unpaid GET returns HTTP 402 with these terms in the body and in the PAYMENT-REQUIRED header. Pay over x402, retry, and receive the signed result. You are not charged for a 400, 422 or 5xx."
    }
   }
  },
  "/screen-multi/preview": {
   "get": {
    "operationId": "screenMultiPreview",
    "summary": "Free signed sample of screen-multi (fixed demo address)",
    "responses": {
     "200": {
      "description": "Signed fixed sample; input ignored",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ScreenPreview"
        }
       }
      }
     }
    }
   }
  },
  "/screen-url": {
   "get": {
    "operationId": "screenUrl",
    "summary": "Screen the payee(s) of an x402 endpoint before you pay it",
    "parameters": [
     {
      "name": "url",
      "in": "query",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uri"
      },
      "description": "Public https x402 endpoint URL whose payee(s) to screen"
     }
    ],
    "responses": {
     "200": {
      "description": "Signed result",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ScreenUrlResult"
        }
       }
      }
     },
     "400": {
      "description": "Input is not a recognised crypto address (for /screen-url not an https URL). Returned BEFORE the payment gate; not charged. An empty or absent address/url returns the normal 402, as x402 discovery requires.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/InvalidInput"
        }
       }
      }
     },
     "402": {
      "description": "Payment required (x402). Terms also in the PAYMENT-REQUIRED response header.",
      "headers": {
       "PAYMENT-REQUIRED": {
        "schema": {
         "type": "string"
        },
        "description": "Base64 x402 payment requirements"
       }
      },
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/PaymentRequired"
        }
       }
      }
     },
     "422": {
      "description": "Target is reachable but is not a usable x402 endpoint (not_402, no_accepts or no_payTo); not charged",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "502": {
      "description": "Could not fetch the target: dns failure, timeout, redirect refused, oversize header or body, or fetch error; not charged",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "x-402": {
     "scheme": "exact",
     "price": "0.01 USDC per call",
     "version": 2,
     "accepts": [
      {
       "scheme": "exact",
       "network": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
       "asset": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
       "amount": "10000",
       "payTo": "35tCuyL3E7M88jfhTeEaRxhrbuKFyQLWgxJQyf5QcLLe",
       "maxTimeoutSeconds": 300,
       "extra": {
        "feePayer": "D6ZhtNQ5nT9ZnTHUbqXZsTx5MH2rPFiBBggX4hY1WePM"
       },
       "maxAmountRequired": "10000"
      },
      {
       "scheme": "exact",
       "network": "eip155:8453",
       "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
       "amount": "10000",
       "payTo": "0xc87a06DEE4c0E85912296002617120BBfd5EF990",
       "maxTimeoutSeconds": 300,
       "extra": {
        "name": "USD Coin",
        "version": "2"
       },
       "maxAmountRequired": "10000"
      }
     ],
     "note": "Unpaid GET returns HTTP 402 with these terms in the body and in the PAYMENT-REQUIRED header. Pay over x402, retry, and receive the signed result. You are not charged for a 400, 422 or 5xx."
    }
   }
  },
  "/screen-url/preview": {
   "get": {
    "operationId": "screenUrlPreview",
    "summary": "Free signed sample of screen-url (fixed demo target)",
    "responses": {
     "200": {
      "description": "Signed fixed sample; input ignored",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ScreenUrlPreview"
        }
       }
      }
     },
     "429": {
      "description": "Free preview daily limit reached",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "503": {
      "description": "Demo target temporarily unreachable",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  }
 },
 "components": {
  "schemas": {
   "ListEntry": {
    "type": "object",
    "properties": {
     "list": {
      "type": "string",
      "enum": [
       "OFAC",
       "UN",
       "EU",
       "HMT"
      ],
      "description": "HMT is the UK list"
     },
     "matched": {
      "type": [
       "boolean",
       "null"
      ]
     },
     "list_version_date": {
      "type": [
       "string",
       "null"
      ]
     },
     "chain": {
      "type": "string"
     },
     "entry_id": {
      "type": [
       "string",
       "null"
      ]
     },
     "note": {
      "type": "string"
     }
    },
    "required": [
     "list",
     "matched",
     "list_version_date"
    ]
   },
   "ListHealth": {
    "type": "object",
    "additionalProperties": {
     "type": "object",
     "properties": {
      "available": {
       "type": "boolean"
      },
      "version_date": {
       "type": [
        "string",
        "null"
       ]
      },
      "note": {
       "type": [
        "string",
        "null"
       ]
      }
     },
     "required": [
      "available"
     ]
    },
    "description": "Per list health keyed by OFAC, UN, EU, HMT"
   },
   "ScreenResult": {
    "type": "object",
    "properties": {
     "address": {
      "type": "string"
     },
     "chain": {
      "type": [
       "string",
       "null"
      ],
      "description": "Advisory hint echoed back; matching is global by address value"
     },
     "sanctioned": {
      "type": [
       "boolean",
       "null"
      ]
     },
     "matched_label": {
      "type": [
       "string",
       "null"
      ]
     },
     "verdict": {
      "type": "string",
      "enum": [
       "clean",
       "deny",
       "indeterminate_ofac_unavailable"
      ]
     },
     "sdn_snapshot_at": {
      "type": [
       "string",
       "null"
      ],
      "format": "date-time"
     },
     "sources": {
      "type": "object",
      "properties": {
       "ofac_sdn": {
        "type": "string"
       },
       "un": {
        "type": "string"
       },
       "eu": {
        "type": "string"
       },
       "hmt": {
        "type": "string"
       }
      }
     },
     "coverage": {
      "type": "object",
      "properties": {
       "lists": {
        "type": "array",
        "items": {
         "type": "string"
        }
       },
       "malicious_heuristic": {
        "type": "string"
       }
      }
     },
     "disclaimer": {
      "type": "string"
     },
     "generated_at": {
      "type": "string",
      "format": "date-time"
     },
     "lists": {
      "type": "array",
      "items": {
       "type": "object",
       "properties": {
        "list": {
         "type": "string",
         "enum": [
          "OFAC",
          "UN",
          "EU",
          "HMT"
         ],
         "description": "HMT is the UK list"
        },
        "matched": {
         "type": [
          "boolean",
          "null"
         ]
        },
        "list_version_date": {
         "type": [
          "string",
          "null"
         ]
        },
        "chain": {
         "type": "string"
        },
        "entry_id": {
         "type": [
          "string",
          "null"
         ]
        },
        "note": {
         "type": "string"
        }
       },
       "required": [
        "list",
        "matched",
        "list_version_date"
       ]
      }
     },
     "list_health": {
      "type": "object",
      "additionalProperties": {
       "type": "object",
       "properties": {
        "available": {
         "type": "boolean"
        },
        "version_date": {
         "type": [
          "string",
          "null"
         ]
        },
        "note": {
         "type": [
          "string",
          "null"
         ]
        }
       },
       "required": [
        "available"
       ]
      },
      "description": "Per list health keyed by OFAC, UN, EU, HMT"
     },
     "any_list_match": {
      "type": "boolean"
     },
     "request_id": {
      "type": "string",
      "description": "Echoed and signed only when supplied"
     },
     "signed_by": {
      "type": "string",
      "description": "EIP-191 signer address",
      "example": "0x57fF0F084Cba33e6761503f90eEF0Da9F159350c"
     },
     "signature": {
      "type": "string",
      "description": "EIP-191 personal_sign over the response without signed_by and signature, serialized as JSON with sorted keys, compact separators (',' and ':') and ASCII escaping (Python json.dumps(sort_keys=True, separators=(',', ':'), ensure_ascii=True)). The free previews follow the same rule."
     }
    },
    "required": [
     "address",
     "verdict",
     "sanctioned",
     "matched_label",
     "sdn_snapshot_at",
     "sources",
     "coverage",
     "lists",
     "list_health",
     "any_list_match",
     "signed_by",
     "signature"
    ]
   },
   "ScreenPreview": {
    "allOf": [
     {
      "$ref": "#/components/schemas/ScreenResult"
     },
     {
      "type": "object",
      "properties": {
       "preview": {
        "type": "boolean"
       },
       "demo_address": {
        "type": "string"
       },
       "input_ignored": {
        "type": "boolean"
       },
       "note": {
        "type": "string"
       },
       "demo_note": {
        "type": "string"
       }
      }
     }
    ]
   },
   "Payee": {
    "type": "object",
    "properties": {
     "network": {
      "type": "string"
     },
     "payTo": {
      "type": "string"
     },
     "asset": {
      "type": "string"
     },
     "amount": {
      "type": "string"
     },
     "scheme": {
      "type": "string"
     },
     "accepts_count": {
      "type": "integer"
     },
     "verdict": {
      "type": "string",
      "enum": [
       "clean",
       "deny",
       "review"
      ]
     },
     "reason": {
      "type": [
       "string",
       "null"
      ]
     },
     "lists": {
      "type": "array",
      "items": {
       "type": "object",
       "properties": {
        "list": {
         "type": "string",
         "enum": [
          "OFAC",
          "UN",
          "EU",
          "HMT"
         ],
         "description": "HMT is the UK list"
        },
        "matched": {
         "type": [
          "boolean",
          "null"
         ]
        },
        "list_version_date": {
         "type": [
          "string",
          "null"
         ]
        },
        "chain": {
         "type": "string"
        },
        "entry_id": {
         "type": [
          "string",
          "null"
         ]
        },
        "note": {
         "type": "string"
        }
       },
       "required": [
        "list",
        "matched",
        "list_version_date"
       ]
      }
     }
    },
    "required": [
     "network",
     "payTo",
     "verdict",
     "lists"
    ]
   },
   "ScreenUrlResult": {
    "type": "object",
    "properties": {
     "url": {
      "type": "string",
      "format": "uri"
     },
     "verdict": {
      "type": "string",
      "enum": [
       "clean",
       "deny",
       "review"
      ]
     },
     "payees": {
      "type": "array",
      "items": {
       "type": "object",
       "properties": {
        "network": {
         "type": "string"
        },
        "payTo": {
         "type": "string"
        },
        "asset": {
         "type": "string"
        },
        "amount": {
         "type": "string"
        },
        "scheme": {
         "type": "string"
        },
        "accepts_count": {
         "type": "integer"
        },
        "verdict": {
         "type": "string",
         "enum": [
          "clean",
          "deny",
          "review"
         ]
        },
        "reason": {
         "type": [
          "string",
          "null"
         ]
        },
        "lists": {
         "type": "array",
         "items": {
          "type": "object",
          "properties": {
           "list": {
            "type": "string",
            "enum": [
             "OFAC",
             "UN",
             "EU",
             "HMT"
            ],
            "description": "HMT is the UK list"
           },
           "matched": {
            "type": [
             "boolean",
             "null"
            ]
           },
           "list_version_date": {
            "type": [
             "string",
             "null"
            ]
           },
           "chain": {
            "type": "string"
           },
           "entry_id": {
            "type": [
             "string",
             "null"
            ]
           },
           "note": {
            "type": "string"
           }
          },
          "required": [
           "list",
           "matched",
           "list_version_date"
          ]
         }
        }
       },
       "required": [
        "network",
        "payTo",
        "verdict",
        "lists"
       ]
      }
     },
     "quote_version": {
      "type": "string"
     },
     "quote_sha256": {
      "type": "string"
     },
     "quote_read_at": {
      "type": "string",
      "format": "date-time"
     },
     "list_health": {
      "type": "object",
      "additionalProperties": {
       "type": "object",
       "properties": {
        "available": {
         "type": "boolean"
        },
        "version_date": {
         "type": [
          "string",
          "null"
         ]
        },
        "note": {
         "type": [
          "string",
          "null"
         ]
        }
       },
       "required": [
        "available"
       ]
      },
      "description": "Per list health keyed by OFAC, UN, EU, HMT"
     },
     "disclaimer": {
      "type": "string"
     },
     "signed_by": {
      "type": "string",
      "example": "0x57fF0F084Cba33e6761503f90eEF0Da9F159350c"
     },
     "signature": {
      "type": "string"
     }
    },
    "required": [
     "url",
     "verdict",
     "payees",
     "signed_by",
     "signature"
    ]
   },
   "ScreenUrlPreview": {
    "allOf": [
     {
      "$ref": "#/components/schemas/ScreenUrlResult"
     },
     {
      "type": "object",
      "properties": {
       "preview": {
        "type": "boolean"
       },
       "input_ignored": {
        "type": "boolean"
       },
       "note": {
        "type": "string"
       },
       "demo_note": {
        "type": "string"
       }
      }
     }
    ]
   },
   "Error": {
    "type": "object",
    "properties": {
     "error": {
      "type": "string"
     },
     "charged": {
      "type": "boolean"
     },
     "detail": {
      "type": "string"
     }
    },
    "required": [
     "error"
    ]
   },
   "PaymentRequired": {
    "type": "object",
    "properties": {
     "x402Version": {
      "type": "integer"
     },
     "error": {
      "type": "string"
     },
     "resource": {
      "type": "string"
     },
     "accepts": {
      "type": "array",
      "items": {
       "type": "object",
       "properties": {
        "scheme": {
         "type": "string"
        },
        "network": {
         "type": "string"
        },
        "asset": {
         "type": "string"
        },
        "payTo": {
         "type": "string"
        },
        "maxAmountRequired": {
         "type": "string"
        },
        "maxTimeoutSeconds": {
         "type": "integer"
        }
       }
      }
     }
    },
    "required": [
     "accepts"
    ]
   },
   "InvalidInput": {
    "type": "object",
    "additionalProperties": false,
    "properties": {
     "error": {
      "type": "string",
      "enum": [
       "invalid_address",
       "missing_url",
       "invalid_url"
      ]
     },
     "charged": {
      "type": "boolean",
      "enum": [
       false
      ]
     },
     "detail": {
      "type": "string"
     }
    },
    "required": [
     "error",
     "charged"
    ]
   }
  }
 }
}
