Crypto KYT poller statistics
Health and progress of the background poller. IT FINISHES NOTHING UNDER THE DEFAULT DRIVER: processScreening calls GetScreening with the record's provider_ref_id, which the mock set to the original transaction id, and CryptoMockService re-derives the status from that same id prefix — so a row screened as processing or pending returns non-final forever, UpdateFromPolling never runs, and pending_count only grows. The route's purpose holds under xziel alone. Takes no parameters and cannot fail on its own. It answers 200 with {"enabled": false, "pending_count": 0} when GetPollerStats returns nil, which happens only when no poller was constructed — see the enabled property. A LIVE poller is a separate matter: its pending_count is not a guaranteed count, because Stats keeps the field at zero when CountPending errors, so {"enabled": true, "pending_count": 0} during a database outage looks exactly like a drained queue.
Authorization
bearerAuth 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
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/v1/kyt/crypto/poller/stats"{
"enabled": true,
"last_run": "2019-08-24T14:15:22Z",
"last_status": "string",
"last_error": "string",
"pending_count": 0
}{
"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"
}Description
Previous Page
Reads the stored row. screened_at is ALWAYS a real timestamp on both routes. Both writers persist ScreenedAt from the driver result — mapTransactionResponse seeds it with time.Now().UTC() before any provider override — and they do so for PROCESSING and PENDING rows too; neither UpdateStatus nor UpdateFromPolling clears the column. Every row these two writers create carries a real timestamp, so neither a zero time nor a null is a not-yet-screened signal — use status. The two routes DO differ in how a null would surface, though: this one runs the column through timeValue, which renders a nil as 0001-01-01T00:00:00Z, while the list route passes the *time.Time straight through and emits null. The column is nullable in the migration, so a row from any other source shows the difference. NEITHER FAILURE ON THIS ROUTE IS THE STATUS IT SHOULD BE — see the 500.