Execute custom SQL queries against your key verification analytics. For complete documentation including available tables, columns, data types, query examples, see the schema reference in the API documentation.
from unkey.py import Unkey
with Unkey(
root_key="<YOUR_BEARER_TOKEN_HERE>",
) as unkey:
res = unkey.analytics.get_verifications(query="SELECT COUNT(*) as total FROM key_verifications_v1 WHERE outcome = 'VALID' AND time >= now() - INTERVAL 7 DAY")
# Handle response
print(res)import { Unkey } from "@unkey/api";
const unkey = new Unkey({
rootKey: process.env["UNKEY_ROOT_KEY"] ?? "",
});
async function run() {
const result = await unkey.analytics.getVerifications({
query: "SELECT COUNT(*) as total FROM key_verifications_v1 WHERE outcome = 'VALID' AND time >= now() - INTERVAL 7 DAY",
});
console.log(result);
}
run();package main
import(
"context"
"os"
unkey "github.com/unkeyed/sdks/api/go/v2"
"github.com/unkeyed/sdks/api/go/v2/models/components"
"log"
)
func main() {
ctx := context.Background()
s := unkey.New(
unkey.WithSecurity(os.Getenv("UNKEY_ROOT_KEY")),
)
res, err := s.Analytics.GetVerifications(ctx, components.V2AnalyticsGetVerificationsRequestBody{
Query: "SELECT COUNT(*) as total FROM key_verifications_v1 WHERE outcome = 'VALID' AND time >= now() - INTERVAL 7 DAY",
})
if err != nil {
log.Fatal(err)
}
if res.V2AnalyticsGetVerificationsResponseBody != nil {
// handle response
}
}curl --request POST \
--url https://api.unkey.com/v2/analytics.getVerifications \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data @- <<EOF
{
"query": "SELECT COUNT(*) as total FROM key_verifications_v1 WHERE outcome = 'VALID' AND time >= now() - INTERVAL 7 DAY"
}
EOFconst options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
query: 'SELECT COUNT(*) as total FROM key_verifications_v1 WHERE outcome = \'VALID\' AND time >= now() - INTERVAL 7 DAY'
})
};
fetch('https://api.unkey.com/v2/analytics.getVerifications', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.unkey.com/v2/analytics.getVerifications",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'query' => 'SELECT COUNT(*) as total FROM key_verifications_v1 WHERE outcome = \'VALID\' AND time >= now() - INTERVAL 7 DAY'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}HttpResponse<String> response = Unirest.post("https://api.unkey.com/v2/analytics.getVerifications")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"query\": \"SELECT COUNT(*) as total FROM key_verifications_v1 WHERE outcome = 'VALID' AND time >= now() - INTERVAL 7 DAY\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.unkey.com/v2/analytics.getVerifications")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"query\": \"SELECT COUNT(*) as total FROM key_verifications_v1 WHERE outcome = 'VALID' AND time >= now() - INTERVAL 7 DAY\"\n}"
response = http.request(request)
puts response.read_body{
"meta": {
"requestId": "req_123"
},
"data": [
{
"outcome": "VALID",
"count": 1234,
"time": 1696118400000
},
{
"outcome": "RATE_LIMITED",
"count": 56,
"time": 1696118400000
}
]
}{
"meta": {
"requestId": "req_123"
},
"error": {
"detail": "Property foo is required but is missing.",
"status": 404,
"title": "Not Found",
"type": "https://unkey.com/docs/errors/unkey/resource/not_found",
"errors": [
{
"location": "body.permissions[0].name",
"message": "Must be at least 3 characters long",
"fix": "Ensure the name uses only alphanumeric characters, underscores, and hyphens"
}
]
}
}{
"meta": {
"requestId": "req_123"
},
"error": {
"detail": "Property foo is required but is missing.",
"status": 404,
"title": "Not Found",
"type": "https://unkey.com/docs/errors/unkey/resource/not_found"
}
}{
"meta": {
"requestId": "req_123"
},
"error": {
"detail": "Property foo is required but is missing.",
"status": 404,
"title": "Not Found",
"type": "https://unkey.com/docs/errors/unkey/resource/not_found"
}
}{
"meta": {
"requestId": "req_123"
},
"error": {
"detail": "Property foo is required but is missing.",
"status": 404,
"title": "Not Found",
"type": "https://unkey.com/docs/errors/unkey/resource/not_found"
}
}{
"meta": {
"requestId": "req_123"
},
"error": {
"detail": "Property foo is required but is missing.",
"status": 404,
"title": "Not Found",
"type": "https://unkey.com/docs/errors/unkey/resource/not_found"
}
}{
"meta": {
"requestId": "req_123"
},
"error": {
"detail": "Property foo is required but is missing.",
"status": 404,
"title": "Not Found",
"type": "https://unkey.com/docs/errors/unkey/resource/not_found"
}
}{
"meta": {
"requestId": "req_123"
},
"error": {
"detail": "Property foo is required but is missing.",
"status": 404,
"title": "Not Found",
"type": "https://unkey.com/docs/errors/unkey/resource/not_found"
}
}{
"meta": {
"requestId": "req_123"
},
"error": {
"detail": "Property foo is required but is missing.",
"status": 404,
"title": "Not Found",
"type": "https://unkey.com/docs/errors/unkey/resource/not_found"
}
}Authorizations
Unkey uses bearer tokens for authentication. Public integrations use root keys, while the dashboard proxy uses short-lived JWTs. To authenticate, include the token in the Authorization header of each request:
Authorization: Bearer unkey_123
Root keys have specific permissions attached to them, controlling what operations they can perform. Legacy permissions use tuple strings like api.*.create_key; resource permissions use Unkey Resource Names plus actions, like unkey:v1:ws_123:keyspaces/*#create_key.
Security best practices:
- Keep root keys secure and never expose them in client-side code
- Use different root keys for different environments
- Rotate keys periodically, especially after team member departures
- Create keys with minimal necessary permissions following least privilege principle
- Monitor key usage with audit logs.
Body
SQL query to execute against your analytics data. Only SELECT queries are allowed.
"SELECT COUNT(*) as total FROM key_verifications_v1 WHERE outcome = 'VALID' AND time >= now() - INTERVAL 7 DAY"
Response
Query executed successfully
Metadata object included in every API response. This provides context about the request and is essential for debugging, audit trails, and support inquiries. The requestId is particularly important when troubleshooting issues with the Unkey support team.
Show child attributes
Show child attributes
Array of verification rows returned by the query. Fields vary based on the SQL SELECT clause.
[ { "outcome": "VALID", "count": 1234, "time": 1696118400000 }, { "outcome": "RATE_LIMITED", "count": 56, "time": 1696118400000 } ]
Was this page helpful?
from unkey.py import Unkey
with Unkey(
root_key="<YOUR_BEARER_TOKEN_HERE>",
) as unkey:
res = unkey.analytics.get_verifications(query="SELECT COUNT(*) as total FROM key_verifications_v1 WHERE outcome = 'VALID' AND time >= now() - INTERVAL 7 DAY")
# Handle response
print(res)import { Unkey } from "@unkey/api";
const unkey = new Unkey({
rootKey: process.env["UNKEY_ROOT_KEY"] ?? "",
});
async function run() {
const result = await unkey.analytics.getVerifications({
query: "SELECT COUNT(*) as total FROM key_verifications_v1 WHERE outcome = 'VALID' AND time >= now() - INTERVAL 7 DAY",
});
console.log(result);
}
run();package main
import(
"context"
"os"
unkey "github.com/unkeyed/sdks/api/go/v2"
"github.com/unkeyed/sdks/api/go/v2/models/components"
"log"
)
func main() {
ctx := context.Background()
s := unkey.New(
unkey.WithSecurity(os.Getenv("UNKEY_ROOT_KEY")),
)
res, err := s.Analytics.GetVerifications(ctx, components.V2AnalyticsGetVerificationsRequestBody{
Query: "SELECT COUNT(*) as total FROM key_verifications_v1 WHERE outcome = 'VALID' AND time >= now() - INTERVAL 7 DAY",
})
if err != nil {
log.Fatal(err)
}
if res.V2AnalyticsGetVerificationsResponseBody != nil {
// handle response
}
}curl --request POST \
--url https://api.unkey.com/v2/analytics.getVerifications \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data @- <<EOF
{
"query": "SELECT COUNT(*) as total FROM key_verifications_v1 WHERE outcome = 'VALID' AND time >= now() - INTERVAL 7 DAY"
}
EOFconst options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
query: 'SELECT COUNT(*) as total FROM key_verifications_v1 WHERE outcome = \'VALID\' AND time >= now() - INTERVAL 7 DAY'
})
};
fetch('https://api.unkey.com/v2/analytics.getVerifications', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.unkey.com/v2/analytics.getVerifications",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'query' => 'SELECT COUNT(*) as total FROM key_verifications_v1 WHERE outcome = \'VALID\' AND time >= now() - INTERVAL 7 DAY'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}HttpResponse<String> response = Unirest.post("https://api.unkey.com/v2/analytics.getVerifications")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"query\": \"SELECT COUNT(*) as total FROM key_verifications_v1 WHERE outcome = 'VALID' AND time >= now() - INTERVAL 7 DAY\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.unkey.com/v2/analytics.getVerifications")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"query\": \"SELECT COUNT(*) as total FROM key_verifications_v1 WHERE outcome = 'VALID' AND time >= now() - INTERVAL 7 DAY\"\n}"
response = http.request(request)
puts response.read_body{
"meta": {
"requestId": "req_123"
},
"data": [
{
"outcome": "VALID",
"count": 1234,
"time": 1696118400000
},
{
"outcome": "RATE_LIMITED",
"count": 56,
"time": 1696118400000
}
]
}{
"meta": {
"requestId": "req_123"
},
"error": {
"detail": "Property foo is required but is missing.",
"status": 404,
"title": "Not Found",
"type": "https://unkey.com/docs/errors/unkey/resource/not_found",
"errors": [
{
"location": "body.permissions[0].name",
"message": "Must be at least 3 characters long",
"fix": "Ensure the name uses only alphanumeric characters, underscores, and hyphens"
}
]
}
}{
"meta": {
"requestId": "req_123"
},
"error": {
"detail": "Property foo is required but is missing.",
"status": 404,
"title": "Not Found",
"type": "https://unkey.com/docs/errors/unkey/resource/not_found"
}
}{
"meta": {
"requestId": "req_123"
},
"error": {
"detail": "Property foo is required but is missing.",
"status": 404,
"title": "Not Found",
"type": "https://unkey.com/docs/errors/unkey/resource/not_found"
}
}{
"meta": {
"requestId": "req_123"
},
"error": {
"detail": "Property foo is required but is missing.",
"status": 404,
"title": "Not Found",
"type": "https://unkey.com/docs/errors/unkey/resource/not_found"
}
}{
"meta": {
"requestId": "req_123"
},
"error": {
"detail": "Property foo is required but is missing.",
"status": 404,
"title": "Not Found",
"type": "https://unkey.com/docs/errors/unkey/resource/not_found"
}
}{
"meta": {
"requestId": "req_123"
},
"error": {
"detail": "Property foo is required but is missing.",
"status": 404,
"title": "Not Found",
"type": "https://unkey.com/docs/errors/unkey/resource/not_found"
}
}{
"meta": {
"requestId": "req_123"
},
"error": {
"detail": "Property foo is required but is missing.",
"status": 404,
"title": "Not Found",
"type": "https://unkey.com/docs/errors/unkey/resource/not_found"
}
}{
"meta": {
"requestId": "req_123"
},
"error": {
"detail": "Property foo is required but is missing.",
"status": 404,
"title": "Not Found",
"type": "https://unkey.com/docs/errors/unkey/resource/not_found"
}
}