# Bewijs toevoegen

> Schrijf data weg met de Tidal Control GraphQL API. Upload een bewijsbestand, maak een uitvoeringstaak op een maatregel aan en koppel het bestand, met Python.

Source: https://tidalcontrol.com/nl/docs/api/adding-evidence

Het grootste deel van deze handleiding gaat over het lezen van data, maar de API kan via mutations ook data **wegschrijven**. Deze pagina doorloopt een volledig voorbeeld: een eigen integratie die een bewijsbestand aan een maatregel toevoegt door een uitvoeringstaak aan te maken en het bestand daaraan te koppelen.

> **warning:**

Mutations vereisen een token met **schrijfrechten**. Authenticeer via de [Device Authorization Grant](/docs/api/authentication), zodat het token namens een gebruiker met de rol **Regular User** of **Super User** handelt. Read-only [machine-to-machine-credentials](/docs/api/authentication) kunnen geen mutations uitvoeren.

## Hoe het werkt

Bewijs in Tidal Control is een **document** dat aan een activiteit is gekoppeld. Bewijs aan een maatregel toevoegen bestaat uit vier stappen:

1. Zoek de maatregel waaraan je bewijs wilt toevoegen
2. Upload het bewijsbestand als document
3. Maak een uitvoeringstaak aan die aan de maatregel is gekoppeld
4. Koppel het document als bewijs aan de task

## Stap 1: De maatregel zoeken

Zoek de maatregel op naam om het `id` op te halen:

```graphql
query FindControl($filter: ControlFilter) {
  controls_paged(first: 1, filter: $filter) {
    edges {
      node {
        id
        sequenceId
        name
      }
    }
  }
}
```

Variabelen:

```json
{ "filter": { "search": "Access control policy" } }
```

## Stap 2: Het bewijsbestand uploaden

Documenten worden geüpload via een REST-endpoint (geen GraphQL), als `multipart/form-data` op het veld `files`. Gebruik hetzelfde Bearer-token:

```bash
curl -s -X POST https://portal.tidalcontrol.com/documents \
  -H "Authorization: Bearer {access_token}" \
  -F "files=@evidence.pdf"
```

Het antwoord is een array van de geüploade documenten:

```json
[
  {
    "id": "11111111-1111-1111-1111-111111111111",
    "name": "evidence.pdf",
    "type": "application/pdf"
  }
]
```

Bewaar het document-`id` voor de volgende stappen.

> **info:**

De maximale uploadgrootte is **128 MB** per verzoek. Je kunt meerdere bestanden in één verzoek uploaden door het veld `files` te herhalen.

## Stap 3: Een uitvoeringstaak op de maatregel aanmaken

Maak een uitvoeringstaak aan en koppel deze via het veld `controls` aan de maatregel uit stap 1:

```graphql
mutation CreateExecution($input: ExecutionInput!) {
  addExecution(input: $input) {
    id
    sequenceId
    name
  }
}
```

Variabelen:

```json
{
  "input": {
    "name": "Quarterly access review",
    "controls": ["22222222-2222-2222-2222-222222222222"]
  }
}
```

Alleen `name` is verplicht. `controls` accepteert een of meer maatregel-`id`'s, en je kunt ook `description`, `expires`, `owners` en `assets` instellen. De mutation geeft het `id` van de nieuwe taak terug.

## Stap 4: Het bewijs koppelen

Koppel het geüploade document aan de task met `addEvidenceToExecution`:

```graphql
mutation AddEvidence($activityId: ID!, $documentIds: [ID!]!) {
  addEvidenceToExecution(activityId: $activityId, documentIds: $documentIds) {
    id
    sequenceId
    evidence {
      id
      document {
        name
      }
    }
  }
}
```

Variabelen:

```json
{
  "activityId": "33333333-3333-3333-3333-333333333333",
  "documentIds": ["11111111-1111-1111-1111-111111111111"]
}
```

Het bewijs verschijnt nu op de taak, die aan je maatregel is gekoppeld.

## Volledig Python-voorbeeld

Dit script knoopt de vier stappen aan elkaar. Het hergebruikt de `get_token()`- en `graphql()`-helpers uit [Authenticatie](/docs/api/authentication).

```python

GRAPHQL_URL = "https://portal.tidalcontrol.com/graphql"
DOCUMENTS_URL = "https://portal.tidalcontrol.com/documents"

def find_control(search, access_token):
    query = """
    query FindControl($filter: ControlFilter) {
      controls_paged(first: 1, filter: $filter) {
        edges { node { id sequenceId name } }
      }
    }
    """
    data = graphql(query, {"filter": {"search": search}}, access_token)
    edges = data["controls_paged"]["edges"]
    if not edges:
        raise RuntimeError(f"Geen maatregel gevonden voor '{search}'")
    return edges[0]["node"]

def upload_document(file_path, access_token):
    with open(file_path, "rb") as f:
        r = requests.post(
            DOCUMENTS_URL,
            headers={"Authorization": f"Bearer {access_token}"},
            files={"files": f},
        )
    r.raise_for_status()
    return r.json()[0]  # eerste geüploade document

def create_execution(name, control_id, access_token):
    mutation = """
    mutation CreateExecution($input: ExecutionInput!) {
      addExecution(input: $input) { id sequenceId name }
    }
    """
    data = graphql(
        mutation,
        {"input": {"name": name, "controls": [control_id]}},
        access_token,
    )
    return data["addExecution"]

def add_evidence(activity_id, document_id, access_token):
    mutation = """
    mutation AddEvidence($activityId: ID!, $documentIds: [ID!]!) {
      addEvidenceToExecution(activityId: $activityId, documentIds: $documentIds) {
        id
        sequenceId
        evidence { id document { name } }
      }
    }
    """
    data = graphql(
        mutation,
        {"activityId": activity_id, "documentIds": [document_id]},
        access_token,
    )
    return data["addEvidenceToExecution"]

if __name__ == "__main__":
    token = get_token()
    access_token = token["access_token"]

    control = find_control("Access control policy", access_token)
    document = upload_document("evidence.pdf", access_token)
    task = create_execution("Quarterly access review", control["id"], access_token)
    result = add_evidence(task["id"], document["id"], access_token)

    print(f"'{document['name']}' toegevoegd aan taak #{result['sequenceId']} op maatregel {control['name']}.")
```

## Bewijs aan een bestaande task koppelen

Bestaat er al een geschikte uitvoeringstaak, sla dan stap 3 over. Zoek de taak met de `activities_paged`-query (zie [Taken exporteren](/docs/api/tasks)) en roep vervolgens `addEvidenceToExecution` aan met het `id`.
