CorebanqCorebanq Developer Docs
KYTv1

List crypto screenings

THE customer_id AND provider FILTERS DO NOT WORK. The handler looks for those keys in the map the shared parser returns, but the parser's switch recognises only limit, offset, sort, stack, distinct, filter, search, search_text and fill_gaps, and search.<field> keys never reach it at all — ParseQueryParameters tests the search. prefix and continues first. Everything else hits default and is dropped. Both keys are therefore always absent, both branches are dead, and every call falls through to the list-all path. Asking for one customer's screenings returns every customer's, with a 200 and no warning. They are documented below as they are declared in the handler, marked inert, because removing them from the spec would hide the divergence rather than record it. Only limit, offset and sort survive into the query.

GET
/v1/kyt/crypto/screenings

Authorization

bearerAuth
AuthorizationBearer <token>

Every route in this module is registered through auth.WrapWithMiddlewares, so all six require a bearer token; none is public. The token is the one the authentication module issues. A missing, unparseable or blacklisted token is the 401 described by Unauthorized401 — and with the rate limiter on, so is a token whose holder lacks the endpoint grant.

In: header

Query Parameters

limit?integer

Default 10, clamped to 100, non-positive becomes 10. Unlike GET /v1/kyt, this route does not re-check the value, so limit=-1 reaches the repository as -1, where list passes it to query.Limit(-1), which GORM treats as no limit, so the call returns every row in kyt.crypto_screenings — on a route with no per-caller scoping.

offset?integer

Default 0. No minimum is declared: parseLimitOffset accepts a negative offset and clamps it to 0, so a schema keyword forbidding it would make a generated client reject a request the server serves.

sort?string

Not validated against an allowlist of sortable fields, unlike the other list routes in this service. Omit it unless you need a specific order: when absent the repository orders by created_at DESC.

customer_id?string

INERT. Dropped by the shared parser before the handler sees it; the list-by-customer branch is unreachable.

provider?string

INERT, for the same reason as customer_id.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/v1/kyt/crypto/screenings"
{
  "data": [
    {
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "transaction_id": "string",
      "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
      "provider": "string",
      "action": "string",
      "kyt_flag": "string",
      "risk_score_level": 0,
      "status": "string",
      "screened_at": "2019-08-24T14:15:22Z",
      "created_at": "2019-08-24T14:15:22Z"
    }
  ],
  "total": 0
}
{
  "status": 400,
  "message": "Invalid input",
  "code": "common.invalid_input",
  "class": "validation"
}
{
  "status": 401,
  "message": "Unauthorized",
  "code": "common.unauthorized",
  "class": "business"
}
{
  "status": 403,
  "message": "No access to the record",
  "code": "common.rbac_no_rec_access",
  "class": "business"
}
{
  "status": 429,
  "message": "Rate limit for 203.0.113.7 to GET:/v1/kyt exceeded.",
  "code": "rate_limits_m.exceeded",
  "class": "temporary",
  "retryable": true
}
{
  "status": 500,
  "message": "Internal server error",
  "code": "common.server_error",
  "class": "business"
}

{
  "overall_status": "unhealthy",
  "message": "Service is shutting down",
  "timestamp": "2026-08-27T15:04:05Z"
}

GETRead both KYT sides of one transaction

Reads kyt.transactions twice, for "<transaction_id>_sender" and "<transaction_id>_recipient". The path segment is the BASE id — the suffixes are appended by the repository and must not be sent. AN UNKNOWN ID IS 200 null, NOT 404. When neither side exists the repository returns (nil, nil) — no error — and the handler serialises that nil straight out, so the body is the four bytes null. A client that dereferences the response without a nil check breaks here, and one that treats any 200 as "found" reports a screening that does not exist. NOT A CONSISTENT SNAPSHOT. GetKYTTransactions issues two independent First queries with no surrounding transaction, so a response can pair a sender side read before a write with a recipient side read after it.

GETList suspended transactions carrying KYT metadata

NOT a list of every KYT response, despite the path. The query filters on transactions.transactions.status = 'suspended' AND kyt.transactions.metadata IS NOT NULL, so this is the review queue: a transaction that was screened and allowed never appears. Ordered by created_at descending. Returns a BARE ARRAY, not the shared list envelope — there is no total, no keys and no total_unfiltered. Only limit and offset are read. Of the rest, search.<field> keys are intercepted before the parser's switch and collected into a search map this module ignores; filter IS recognised and is parsed as JSON, so a malformed value is a real 400; and only genuinely unrecognised keys hit the default branch and vanish. ONE ENTRY PER SIDE, NOT PER TRANSACTION. kyt.transactions holds a row for each half of a transfer — the connector writes <id>_sender and <id>_recipient separately — and both carry the same transaction_id_relation. The query groups by transaction_id_relation, customer_id and created_at, and the two sides differ in the last two, so one suspended transfer yields TWO array entries with the identical transaction_id. A client de-duplicating on transaction_id sees half its page vanish, and limit=10 can mean five transfers.