{
  "openapi": "3.0.1",
  "info": {
    "title": "Consents API",
    "description": "Consents represent the link between a customer in your system and their connection to an accounting system in API.1. Create a consent, then use the consent identifier to invite the customer through the Onboarding Flow.\n\nCreate one-time codes in this API and use them only inside your embedded client integration when starting the Onboarding Flow. Do not expose OTCs in share links because they can be prematurely consumed.\n\nWhere a field requires a standardized language code, use ISO 639-2.\n\n**Consent status** — Each consent has one of the following statuses (use the status name or value in filters):\n\n| Status name | Value | Description |\n|-------------|-------|-------------|\n| CREATED | 0 | The Consent has this status as soon as it is created via the API. |\n| ACCEPTED | 1 | The Consent has this status as soon as Your Customer successfully connects their Accounting System. |\n| REVOKED | 2 | The Consent has this status if you update it, for example, by allowing Your Customer to revoke their Consent. |\n| INACTIVE | 3 | The Consent has this status if the underlying connection is no longer able to connect to the Accounting System. |\n\n**Accounting systems** — Use the lower-case system identifier (for example in query filters and `systemsSettings` dictionaries) when referring to a supported accounting system:\n\n| System Name | System Identifier |\n|-------------|-------------------|\n| Fortnox | fortnox |\n| Visma eAccounting | vismaeaccounting |\n| Bjorn Lunden | bjornlunden |\n| Procountor | procountor |\n| Visma e‑conomic | vismaeconomic |\n| Test.1 | testone |\n| Visma Dinero | vismadinero |\n| Billy | billy |\n| File.1 | fileone |\n| Tripletex | tripletex |\n| Business Central | businesscentral |\n| Visma Netvisor | vismanetvisor |\n| Exact Online | exactonline |\n| QuickBooks Online | quickbooks |\n| Xero | xero |\n| Bokio | bokio |\n",
    "termsOfService": "https://www.zwapgrid.com/terms-and-conditions",
    "contact": {
      "name": "Zwapgrid",
      "url": "https://www.zwapgrid.com",
      "email": "hello@zwapgrid.com"
    },
    "version": "v1"
  },
  "paths": {
    "/api/v1/consents/{consentId}": {
      "get": {
        "tags": [
          "Consents"
        ],
        "summary": "Get a consent",
        "description": "Use this endpoint to fetch the full details of a consent (e.g. after creating one via the Location header, or to check status and system settings for a specific connection).",
        "operationId": "GetConsent",
        "parameters": [
          {
            "name": "consentId",
            "in": "path",
            "description": "Identifier of the consent representing the connection to the accounting system.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-correlation-id",
            "in": "header",
            "description": "Unique identifier used to correlate and trace this request.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Returns a consent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConsentDto"
                }
              }
            }
          },
          "401": {
            "description": "Not authenticated to access this API endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Not authorised to access this API endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "The consent does not exist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Consents"
        ],
        "summary": "Update a consent",
        "description": "Use this endpoint to change the consent display name or to revoke the consent (set status to REVOKED so the customer's connection is no longer active). Send the If-Match header with the ETag from the last GET consent response to avoid overwriting concurrent changes.",
        "operationId": "PatchConsent",
        "parameters": [
          {
            "name": "consentId",
            "in": "path",
            "description": "Identifier of the consent representing the connection to the accounting system.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "description": "Value of the ETag returned as a response header from the get-consent endpoint.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-correlation-id",
            "in": "header",
            "description": "Unique identifier used to correlate and trace this request.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "description": "Request body containing the optional status and name to update.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateConsentDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateConsentDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateConsentDto"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "The consent was updated successfully."
          },
          "400": {
            "description": "The request is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Not authenticated to access this API endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Not authorised to access this API endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "The consent does not exist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "412": {
            "description": "If-Match header does not match Etag - this means that the resource has been changed and now has a different Etag.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Consents"
        ],
        "summary": "Delete a consent",
        "description": "Use this endpoint to permanently remove a consent. After deletion, the consent ID can no longer be used and the customer would need a new consent to reconnect.",
        "operationId": "DeleteConsent",
        "parameters": [
          {
            "name": "consentId",
            "in": "path",
            "description": "Identifier of the consent representing the connection to the accounting system.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-correlation-id",
            "in": "header",
            "description": "Unique identifier used to correlate and trace this request.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "If consent is removed"
          },
          "400": {
            "description": "If request is invalid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/consents": {
      "get": {
        "tags": [
          "Consents"
        ],
        "summary": "List consents",
        "description": "Use this endpoint to retrieve all consents (connections to accounting systems) for your client. Filter by status, source, name, dates, or other query parameters to find specific consents.",
        "operationId": "GetConsents",
        "parameters": [
          {
            "name": "x-correlation-id",
            "in": "header",
            "description": "Unique identifier used to correlate and trace this request.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Count",
            "in": "query",
            "description": "Number of records to return per page.",
            "schema": {
              "maximum": 100,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "CurrentPage",
            "in": "query",
            "description": "One-based index of the page to return.",
            "schema": {
              "maximum": 2147483647,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "CreatedOn",
            "in": "query",
            "description": "Filter by creation date. Format: yyyy-MM-dd.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "UpdatedOn",
            "in": "query",
            "description": "Filter by last update date. Format: yyyy-MM-dd.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "OrderBy",
            "in": "query",
            "description": "Sort order for the results.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Status",
            "in": "query",
            "description": "Filter by consent status. Use the status name or numeric value: CREATED (0), ACCEPTED (1), REVOKED (2), INACTIVE (3).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Source",
            "in": "query",
            "description": "Filter by source (accounting system identifier).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "IsTest",
            "in": "query",
            "description": "Filter by test flag. When true, only test consents are returned.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "SystemSettingsId",
            "in": "query",
            "description": "Filter by the selected system settings ID (the system setting in effect once a consent is accepted).",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Name",
            "in": "query",
            "description": "Filter by consent name.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Returns a list of consents.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConsentDtoPagedResultDto"
                }
              }
            }
          },
          "401": {
            "description": "Not authenticated to access this API endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Not authorised to access this API endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "The client does not exist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Consents"
        ],
        "summary": "Create a consent",
        "description": "Use this endpoint to create a consent that links your customer to a future connection in API.1. After creating, use the Location header to get the consent ID, then create a one-time code (POST /consents/{consentId}/otc) and use it only inside your embedded client integration when starting the Onboarding Flow. Do not expose the OTC in share links because it can be prematurely consumed. The 201 response includes a Location header with the URI of the created consent.",
        "operationId": "PostConsent",
        "parameters": [
          {
            "name": "x-correlation-id",
            "in": "header",
            "description": "Unique identifier used to correlate and trace this request.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "description": "Request body containing the consent name and optional system settings.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateConsentDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateConsentDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/CreateConsentDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "headers": {
              "Location": {
                "description": "URI of the created consent. Use this URL to retrieve the created resource (e.g. GET /api/v1/consents/{consentId}).",
                "schema": {
                  "type": "string",
                  "format": "uri",
                  "example": "/api/v1/consents/3fa85f64-5717-4562-b3fc-2c963f66afa6"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "No body; use the Location header to fetch the created consent."
                }
              }
            },
            "links": {
              "getCreatedConsent": {
                "operationId": "GetConsent",
                "description": "Get the created consent using the Location header from this response."
              }
            }
          },
          "400": {
            "description": "The request is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Not authenticated to access this API endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Not authorised to access this API endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "The consent does not exist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/consents/{consentId}/otc": {
      "post": {
        "tags": [
          "Consents"
        ],
        "summary": "Create a one-time code",
        "description": "Use this endpoint after creating a consent to obtain a one-time code (OTC). Use the OTC only inside your embedded client integration when starting the Onboarding Flow. Do not expose the OTC in share links because it can be prematurely consumed.",
        "operationId": "PostOtc",
        "parameters": [
          {
            "name": "consentId",
            "in": "path",
            "description": "Identifier of the consent representing the connection to the accounting system.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-correlation-id",
            "in": "header",
            "description": "Unique identifier used to correlate and trace this request.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "One-time code was created successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtcDto"
                }
              }
            }
          },
          "400": {
            "description": "The request is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Not authenticated to access this API endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Not authorised to access this API endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "The consent does not exist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ConsentDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The ID of the Consent",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "description": "The name of the Consent",
            "nullable": true
          },
          "status": {
            "$ref": "#/components/schemas/ConsentStatus"
          },
          "source": {
            "type": "string",
            "description": "The source of the consent (i.e. what system has been connected)",
            "nullable": true
          },
          "systemSettingsId": {
            "type": "string",
            "description": "The selected system settings ID once the consent is accepted. Populated when the consent has a single connected system; see systemSettings for the full dictionary of available system settings.",
            "format": "uuid",
            "nullable": true
          },
          "systemSettings": {
            "type": "object",
            "additionalProperties": {
              "type": "string",
              "description": "System settings ID (UUID) for this accounting system (value in the dictionary).",
              "format": "uuid",
              "x-additionalPropertiesName": "System identifier (e.g. fortnox)"
            },
            "description": "\nDictionary of available system settings for the consent.\r\n\nKey: lower-case system identifier (e.g. fortnox, fileone).\r\n\nValue: system settings ID (UUID).\r\n\nSee API description for supported system identifiers.",
            "nullable": true
          },
          "createdOn": {
            "type": "string",
            "description": "The date the consent was created on",
            "format": "date-time"
          },
          "updatedOn": {
            "type": "string",
            "description": "The date the consent was updated on",
            "format": "date-time",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Consent resource returned by get and list endpoints. Represents the link between your customer and their connection to an accounting system.",
        "example": {
          "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
          "name": "Acme Corp - Fortnox",
          "status": 1,
          "source": "Fortnox",
          "systemSettingsId": "a1b2c3d4-e5f6-4a5b-8c9d-1e2f3a4b5c6d",
          "systemSettings": {
            "fileone": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
            "fortnox": "a1b2c3d4-e5f6-4a5b-8c9d-1e2f3a4b5c6d"
          },
          "createdOn": "2024-01-15T10:30:00Z",
          "updatedOn": "2024-01-20T14:45:00Z"
        }
      },
      "ConsentDtoPagedResultDto": {
        "type": "object",
        "properties": {
          "meta": {
            "$ref": "#/components/schemas/PagedResultMetadataDto"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ConsentDto"
            },
            "description": "The list of items for the current page.",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Paginated list response. Contains a page of items and metadata for total count and pagination.",
        "example": {
          "meta": {
            "totalResources": 42,
            "totalPages": 3,
            "currentPage": 1
          },
          "data": [
            {
              "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
              "name": "Acme Corp - Fortnox",
              "status": 1,
              "source": "Fortnox",
              "systemSettingsId": "a1b2c3d4-e5f6-4a5b-8c9d-1e2f3a4b5c6d",
              "systemSettings": {
                "fileone": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                "fortnox": "a1b2c3d4-e5f6-4a5b-8c9d-1e2f3a4b5c6d"
              },
              "createdOn": "2024-01-15T10:30:00Z",
              "updatedOn": "2024-01-20T14:45:00Z"
            }
          ]
        }
      },
      "ConsentStatus": {
        "enum": [
          0,
          1,
          2,
          3
        ],
        "type": "integer",
        "description": "Consent status. Values: CREATED (0), ACCEPTED (1), REVOKED (2), INACTIVE (3).",
        "format": "int32",
        "x-enumNames": [
          "CREATED",
          "ACCEPTED",
          "REVOKED",
          "INACTIVE"
        ]
      },
      "CreateConsentDto": {
        "required": [
          "name"
        ],
        "type": "object",
        "properties": {
          "name": {
            "minLength": 1,
            "type": "string",
            "description": "Display name for the consent (e.g. your customer or integration name)."
          },
          "systemsSettings": {
            "type": "object",
            "additionalProperties": {
              "type": "string",
              "description": "System settings ID (UUID) for this accounting system (value in the dictionary).",
              "format": "uuid",
              "x-additionalPropertiesName": "System identifier (e.g. fortnox)"
            },
            "description": "\nOptional dictionary of available system settings for the consent.\r\n\nKey: lower-case system identifier (e.g. fortnox, fileone).\r\n\nValue: system settings ID (UUID).\r\n\nOmit to use client defaults where applicable.\r\n\nSee API description for supported system identifiers.",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Request body for creating a new consent. Links a customer in your system to a connection that is completed in the Onboarding Flow.",
        "example": {
          "name": "Acme Corp - Fortnox",
          "systemsSettings": {
            "fileone": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
            "fortnox": "a1b2c3d4-e5f6-4a5b-8c9d-1e2f3a4b5c6d"
          }
        }
      },
      "OtcDto": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "description": "The one-time code used by the embedded client integration when starting the Onboarding Flow.",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "One-time code returned when creating an OTC. Use it only inside your embedded client integration when starting the Onboarding Flow. Do not expose it in share links because it can be prematurely consumed.",
        "example": {
          "code": "OTC-7a3b2c1d-4e5f-6a7b-8c9d-0e1f2a3b4c5d"
        }
      },
      "PagedResultMetadataDto": {
        "type": "object",
        "properties": {
          "totalResources": {
            "type": "integer",
            "description": "Total number of resources across all pages.",
            "format": "int32"
          },
          "totalPages": {
            "type": "integer",
            "description": "Total number of pages given the page size.",
            "format": "int32"
          },
          "currentPage": {
            "type": "integer",
            "description": "One-based index of the current page.",
            "format": "int32"
          }
        },
        "additionalProperties": false,
        "description": "Metadata for a paginated result: total count and current page information."
      },
      "ProblemDetails": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "nullable": true
          },
          "title": {
            "type": "string",
            "nullable": true
          },
          "status": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "detail": {
            "type": "string",
            "nullable": true
          },
          "instance": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": {}
      },
      "UpdateConsentDto": {
        "type": "object",
        "properties": {
          "status": {
            "$ref": "#/components/schemas/ConsentStatus"
          },
          "name": {
            "type": "string",
            "description": "New display name for the consent.",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Request body for updating an existing consent. Only provided properties are updated.",
        "example": {
          "status": 2,
          "name": "Acme Corp - Fortnox (revoked)"
        }
      }
    },
    "securitySchemes": {
      "ApiKey": {
        "type": "apiKey",
        "description": "You must generate an API Key by logging into the [Client Portal](https://clients.zwapgrid.com).<br/><br/>You should use the API Key when calling all API endpoints in API.1.",
        "name": "x-api-key",
        "in": "header"
      }
    }
  },
  "security": [
    {
      "ApiKey": []
    }
  ],
  "tags": [
    {
      "name": "Consents",
      "description": "Create, read, update, and delete consents; create one-time codes used in the Onboarding Flow. See the API description for consent statuses and supported accounting systems."
    }
  ]
}
