API-referentie
Controls exporteren
Controls worden geëxporteerd met de controls_paged-query. Elke control bevat zijn categorie, effectiviteitsstatus, gekoppelde risico's, assets en frameworkreferenties.
Basisquery
query ExportControls($first: Int, $after: String, $filter: ControlFilter) {
controls_paged(first: $first, after: $after, filter: $filter) {
edges {
node {
id
sequenceId
customId
name
description
category
notBefore
expires
archived
risks {
id
sequenceId
name
treatment
}
assets {
id
name
}
assignments {
assignmentType
user {
name
email
}
}
controlStatus {
progress {
effectiveness
closedTasks
totalTasks
}
issues {
open
closed
}
}
attributes {
key
value
}
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
Variabelen voor de eerste pagina:
{ "first": 50, "after": null, "filter": {} }
Belangrijke velden
sequenceId— het leesbare nummer zoals getoond in de UI (bijv. C-15)customId— optionele aangepaste identifier (bijv. ISO 27001-controlreferentie)category— de controlcategorie, bijv.ACCESS_CONTROL,DATA_SECURITY_AND_PRIVACYcontrolStatus.progress.effectiveness—UNDETERMINED,INEFFECTIVEofEFFECTIVEcontrolStatus.progress.closedTasks/totalTasks— taakvoltooiingsverhouding
Volledig exportscript (Python)
import requests
import csv
GRAPHQL_URL = "https://portal.tidalcontrol.com/graphql"
QUERY = """
query ExportControls($first: Int, $after: String, $filter: ControlFilter) {
controls_paged(first: $first, after: $after, filter: $filter) {
edges {
node {
id
sequenceId
customId
name
description
category
notBefore
expires
archived
risks { id sequenceId name treatment }
assets { id name }
assignments { assignmentType user { name email } }
controlStatus {
progress { effectiveness closedTasks totalTasks }
issues { open closed }
}
}
}
pageInfo { hasNextPage endCursor }
}
}
"""
def graphql(query, variables, access_token):
r = requests.post(
GRAPHQL_URL,
json={"query": query, "variables": variables},
headers={"Authorization": f"Bearer {access_token}"},
)
r.raise_for_status()
result = r.json()
if "errors" in result:
raise RuntimeError(result["errors"])
return result["data"]
def export_controls(access_token, include_archived=False):
controls = []
cursor = None
control_filter = {"archived": include_archived} if include_archived else {}
while True:
data = graphql(
QUERY,
{"first": 50, "after": cursor, "filter": control_filter},
access_token,
)
page = data["controls_paged"]
controls.extend(edge["node"] for edge in page["edges"])
if not page["pageInfo"]["hasNextPage"]:
break
cursor = page["pageInfo"]["endCursor"]
return controls
def to_csv(controls, output_path):
if not controls:
print("Geen controls gevonden.")
return
with open(output_path, "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow([
"ID", "Volgnummer", "Aangepast ID", "Naam", "Omschrijving",
"Categorie", "Startdatum", "Vervaldatum", "Gearchiveerd",
"Effectiviteit", "Gesloten taken", "Totaal taken",
"Open issues", "Gesloten issues",
"Gekoppelde risico's", "Gekoppelde assets", "Eigenaren",
])
for c in controls:
progress = c["controlStatus"]["progress"]
issues = c["controlStatus"]["issues"]
owners = [
a["user"]["email"]
for a in c["assignments"]
if a["assignmentType"] == "OWNER"
]
writer.writerow([
c["id"],
c["sequenceId"],
c.get("customId", ""),
c["name"],
c.get("description", ""),
c.get("category", ""),
c.get("notBefore", ""),
c.get("expires", ""),
c["archived"],
progress["effectiveness"],
progress["closedTasks"],
progress["totalTasks"],
issues["open"],
issues["closed"],
", ".join(r["name"] for r in c["risks"]),
", ".join(a["name"] for a in c["assets"]),
", ".join(owners),
])
print(f"{len(controls)} controls geëxporteerd naar {output_path}")
if __name__ == "__main__":
ACCESS_TOKEN = "eyJhbGci..."
controls = export_controls(ACCESS_TOKEN)
to_csv(controls, "controls_export.csv")
Filtervoorbeelden
Alleen effectieve controls:
# Filter in Python na het ophalen (effectiviteit zit in controlStatus, niet als top-level filterveld)
effective = [c for c in controls if c["controlStatus"]["progress"]["effectiveness"] == "EFFECTIVE"]
Controls in een specifieke categorie:
{ "filter": { "categories": ["ACCESS_CONTROL"] } }
Controls gekoppeld aan een specifiek framework:
{ "filter": { "frameworks": ["framework-uuid-hier"] } }
Controls met open issues:
met_issues = [c for c in controls if c["controlStatus"]["issues"]["open"] > 0]
Alleen tellen
query {
controls_count(filter: { archived: false })
}
- Vorige
- Risico's exporteren
- Volgende
- Assets exporteren