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.
Dit voorbeeld haalt alleen open issues met hoge prioriteit op:
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