curl --request GET \
--url https://api-uat.dimetrades.com/api/subcategories \
--header 'X-API-Key: <api-key>'import requests
url = "https://api-uat.dimetrades.com/api/subcategories"
headers = {"X-API-Key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-Key': '<api-key>'}};
fetch('https://api-uat.dimetrades.com/api/subcategories', 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-uat.dimetrades.com/api/subcategories",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api-uat.dimetrades.com/api/subcategories"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-Key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api-uat.dimetrades.com/api/subcategories")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-uat.dimetrades.com/api/subcategories")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-Key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"data": {
"success": true,
"subcategories": [
{
"id": 67,
"name": "Bitcoin",
"description": null,
"imageUrl": null,
"categoryId": 34,
"isActive": true,
"displayOrder": 0,
"parentId": null,
"level": 1,
"hasChildren": false,
"activeEventsCount": 15,
"createdAt": "2026-07-22T09:29:00.030Z",
"updatedAt": "2026-07-22T09:29:00.030Z"
}
],
"pagination": {
"count": 6,
"totalCount": 6,
"hasPreviousPage": false,
"hasNextPage": false
}
},
"errors": []
}List subcategories
Returns subcategories — the level you filter events by. For crypto and
financial markets these are per-asset (Bitcoin, Gold, EUR/USD), so this
is where you look up the subcategoryId to pass to GET /events.
No user token required — send your X-API-Key only.
Only subcategories with active events are returned
A subcategory whose activeEventsCount is 0 is omitted — an empty
sport or asset never appears in the list. pagination.totalCount,
count and hasNextPage describe the filtered list, so pages are always
full until the last one. Because the count follows the status parameter,
changing status can change which rows come back (a subcategory with
only settled events is absent from the default list but present with
status=settled).
Two behaviours that surprise people
subCategoryId returns the CHILDREN of that subcategory, not the
subcategory itself. Passing subCategoryId=81 (Metals) returns Gold and
Silver; passing a leaf id such as 82 (Gold) returns an empty list,
because Gold has no children. Note also the capital C in the parameter
name — unlike subcategoryId on GET /events.
withCadence=true mixes virtual entries into the subcategories array.
Those entries are { cadence, count, isVirtual: true } — synthesized cadence
buckets for a navigation menu, not rows from the subcategories table. They
have no id and cannot be used as a subcategoryId. Separate them by
testing isVirtual.
Three further quirks: the buckets are only emitted when the page contains
at least one real subcategory (a page with none returns no buckets either);
their counts honour categoryId but ignore subCategoryId and
isActive; and count means currently-live events, not all events at
that cadence.
Query parameters are integers here
categoryId, subCategoryId, page and limit are validated as numbers
on this endpoint, not as strings of digits the way GET /events expects
them. Unknown parameters are rejected with 400.
curl --request GET \
--url https://api-uat.dimetrades.com/api/subcategories \
--header 'X-API-Key: <api-key>'import requests
url = "https://api-uat.dimetrades.com/api/subcategories"
headers = {"X-API-Key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-Key': '<api-key>'}};
fetch('https://api-uat.dimetrades.com/api/subcategories', 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-uat.dimetrades.com/api/subcategories",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api-uat.dimetrades.com/api/subcategories"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-Key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api-uat.dimetrades.com/api/subcategories")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-uat.dimetrades.com/api/subcategories")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-Key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"data": {
"success": true,
"subcategories": [
{
"id": 67,
"name": "Bitcoin",
"description": null,
"imageUrl": null,
"categoryId": 34,
"isActive": true,
"displayOrder": 0,
"parentId": null,
"level": 1,
"hasChildren": false,
"activeEventsCount": 15,
"createdAt": "2026-07-22T09:29:00.030Z",
"updatedAt": "2026-07-22T09:29:00.030Z"
}
],
"pagination": {
"count": 6,
"totalCount": 6,
"hasPreviousPage": false,
"hasNextPage": false
}
},
"errors": []
}Authorizations
ISV / partner credential — public half. Required on every request.
Identifies the integration partner (ISV) making the call. Issued by Dime
Trades when the ISV is onboarded and sent on every /partner/* endpoint:
X-API-Key: dt_pk_live_7f3c9a2e5b18
- On the two partner endpoints that create accounts or issue tokens (
POST /partner/customers,POST /partner/customers/login), it is accompanied byX-API-Secretand is the only authentication — there is no user token yet. - On every other partner endpoint it is sent alongside the user's
Authorization: Bearer <token>: the API key says which platform is calling, the bearer token says which user it is calling for.
Credentials are scoped to one or more brands; using a key with a brandId outside that scope returns 403. Staging and production keys are separate.
The key identifies your platform — treat it as a backend credential.
Query Parameters
Filter by parent category.
x >= 134
Return the children of this subcategory. A leaf id returns an empty list. Mind the capital C.
x >= 181
Accepted for compatibility. Only active subcategories are ever returned, so isActive=false does not return inactive ones.
Which event status activeEventsCount should count. Defaults to live and open events together. Subcategories with a count of 0 for the chosen status are not returned, so this also decides which rows appear.
pending, open, live, halted, closed, settled, expired, terminated Include cadence buckets. Adds virtual CadenceBucket entries to the start of subcategories, and a cadenceSubcategories array to each real subcategory. See the warning above.
x >= 1Page size. Applies to real subcategories only, not to the virtual entries. Rows are ordered by displayOrder, then id, so paging is stable even when displayOrder is 0 throughout.
x >= 1