API-referentie
Data opvragen
Alle lijstquery's in de Tidal Control API volgen dezelfde patronen voor paginering, filtering en sortering. Leer ze eenmalig en ze gelden overal.
Verzoekstructuur
Elk GraphQL-verzoek is een POST naar https://portal.tidalcontrol.com/graphql met een JSON-body:
{
"query": "...",
"variables": { ... }
}
Gebruik altijd variables in plaats van waarden rechtstreeks in de querystring te plaatsen — dat houdt query's leesbaar en voorkomt injectieproblemen.
Paginering
Alle *_paged-query's gebruiken cursor-gebaseerde paginering volgens de Relay Connection-specificatie. Vraag een pagina op met first (paginagrootte) en after (cursor van de vorige pagina):
query ExportRisks($first: Int, $after: String) {
risks_paged(first: $first, after: $after) {
edges {
node {
id
name
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
Variabelen:
{ "first": 50, "after": null }
Als pageInfo.hasNextPage true is, geef je pageInfo.endCursor door als after in het volgende verzoek.
Alle pagina's ophalen (Python)
def fetch_all(graphql_fn, query, page_size=50):
"""Haal alle pagina's op van een gepagineerde query."""
results = []
cursor = None
while True:
data = graphql_fn(query, {"first": page_size, "after": cursor})
key = next(iter(data))
page = data[key]
results.extend(edge["node"] for edge in page["edges"])
if not page["pageInfo"]["hasNextPage"]:
break
cursor = page["pageInfo"]["endCursor"]
return results
Een paginagrootte van 50 is een goede standaard. Je kunt hoger gaan, maar zeer grote pagina's kunnen de responstijd verlengen.
Filtering
Geef een filter-argument mee om resultaten te beperken. Elke entiteit heeft zijn eigen filtertype met relevante velden. Alle filtervelden zijn optioneel — laat velden die je niet nodig hebt weg.
Voorbeeld — alleen open, hoge-prioriteit issues ophalen:
query FilteredIssues($filter: IssueFilter) {
issues_paged(first: 50, filter: $filter) {
edges {
node {
id
name
priority
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
Variabelen:
{
"filter": {
"closed": false,
"priority": ["HIGH"]
}
}
Veelgebruikte filtervelden
Beschikbaar op de meeste entiteiten:
archived: Boolean— gearchiveerde records in- of uitsluitenassignees: [UUID!]— filteren op toegewezen gebruikers-ID'ssearch: String— vrije-tekstzoekactie op naam/omschrijving
Activiteiten (issues, taken):
closed: Boolean— open of gesloten activiteitencontrols: [UUID!]— activiteiten gekoppeld aan specifieke controlsassets: [UUID!]— activiteiten gekoppeld aan specifieke assetsstatus: [ActivityDueStatus!]—NOT_DUE_SOON,DUE_SOON,OVERDUE,NOT_SET
Alleen issues:
priority: [Priority!]—LOW,MEDIUM,HIGHtype: [IssueType!]— bijv.AUDIT_FINDING,INCIDENT,CONTROL_GAP
Risico's en controls:
frameworks: [UUID!]— gekoppeld aan specifieke frameworksreferences: [UUID!]— gekoppeld aan specifieke frameworkreferenties
Sortering
Geef een sort-array mee om de volgorde van resultaten te bepalen. Elk sorteerelement geeft een field-naam en een optionele direction (ASC of DESC) aan:
query SortedRisks {
risks_paged(
first: 50,
sort: [{ field: "sequenceId", direction: ASC }]
) {
edges {
node {
sequenceId
name
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
Je kunt meerdere sorteervelden opgeven. Veelgebruikte velden zijn name, sequenceId, createdDate, notBefore en expires.
Records tellen
Gebruik *_count-query's om een totaaltelling op te halen zonder alle gegevens op te vragen:
query {
risks_count
controls_count(filter: { archived: false })
issues_count(filter: { closed: false, priority: ["HIGH"] })
}
Foutafhandeling
Een geslaagd antwoord heeft altijd HTTP-statuscode 200, ook wanneer de GraphQL-query zelf fouten bevat. Controleer de errors-array in de response-body:
{
"data": null,
"errors": [
{
"message": "Unauthorized",
"locations": [{ "line": 1, "column": 1 }]
}
]
}
Veelvoorkomende fouten:
- Unauthorized — je token ontbreekt of is verlopen; authenticeer opnieuw
- Field does not exist — controleer de veldnaam in het schema
- Variable … expected type … — een filtervariabele heeft het verkeerde type
- Vorige
- Authenticatie
- Volgende
- Risico's exporteren