{
  "openapi": "3.1.0",
  "info": {
    "title": "AgencyAccess API",
    "version": "2.0.0",
    "summary": "Create clients and access requests, embed them in your portal, and follow their progress.",
    "description": "The AgencyAccess API (V2) lets your platform create clients and access requests, list the accounts and services you can request, embed requests in your client portal, and receive signed webhooks as clients grant access. Every response is JSON wrapped in `data` and `meta`.",
    "contact": {
      "name": "AgencyAccess support",
      "email": "support@agencyaccess.co",
      "url": "https://www.agencyaccess.co/docs/api"
    }
  },
  "servers": [
    {
      "url": "https://api.agencyaccess.co/api/v2",
      "description": "Production"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Clients",
      "x-slug": "clients",
      "description": "The businesses you request access from. Store your own ID on each client as `externalClientId` to find it again without keeping ours."
    },
    {
      "name": "Requests",
      "x-slug": "requests",
      "description": "Access requests: the link a client opens to grant your agency access to their accounts, and the progress of each requested service."
    },
    {
      "name": "Accounts and services",
      "x-slug": "catalog",
      "description": "What a request can ask for: your agency's connected accounts that access is granted to, and the services and roles that can be requested."
    },
    {
      "name": "Webhooks",
      "x-slug": "webhooks",
      "description": "Endpoints on your server that receive signed events as requests change. Deliveries are retried for 24 hours."
    },
    {
      "name": "Usage",
      "x-slug": "usage",
      "description": "Your plan and how much of this month's access link allowance you have used."
    },
    {
      "name": "Account",
      "x-slug": "account",
      "description": "The API key in use and its agency, to check a setup."
    }
  ],
  "paths": {
    "/me": {
      "get": {
        "tags": [
          "Account"
        ],
        "operationId": "getMe",
        "summary": "Retrieve the current key",
        "description": "Returns the agency and API key the request was authenticated with, and the key's scopes. Needs no scope.",
        "responses": {
          "200": {
            "description": "The key and its agency.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Me"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            },
            "x-example": {
              "agency": {
                "id": "0b3e5f7a-1c2d-4e6f-8a9b-0c1d2e3f4a5b",
                "name": "Acme Marketing"
              },
              "apiKey": {
                "id": "9e8d7c6b-5a49-4382-a1b0-c9d8e7f6a5b4",
                "scopes": [
                  "clients:read",
                  "clients:create",
                  "requests:read",
                  "requests:create"
                ]
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          }
        }
      }
    },
    "/clients": {
      "post": {
        "tags": [
          "Clients"
        ],
        "operationId": "createClient",
        "summary": "Create a client",
        "description": "Creates a client. Set `externalClientId` to your own ID for the client so you can find it again with `GET /clients?externalClientId=`; it is unique within your agency and cannot be changed once set. Emails are not unique: creating a client with an existing email makes another client.",
        "x-scope": "clients:create",
        "x-idempotent": true,
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "A unique value per create, such as a UUID (1-255 visible ASCII characters). Retrying with the same key and body returns the original result instead of creating another object; keys are kept for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClientCreate"
              },
              "example": {
                "name": "Jamie Rivera",
                "email": "jamie@northwindcoffee.com",
                "company": "Northwind Coffee",
                "website": "https://northwindcoffee.com",
                "externalClientId": "crm-4821",
                "metadata": {
                  "accountManager": "Priya"
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new client.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Client"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            },
            "x-example": {
              "id": "7c1e9f52-3b8a-4d2e-9a61-5f0c2d8b4e17",
              "externalClientId": "crm-4821",
              "name": "Jamie Rivera",
              "email": "jamie@northwindcoffee.com",
              "company": "Northwind Coffee",
              "website": "https://northwindcoffee.com",
              "language": "English",
              "metadata": {
                "accountManager": "Priya"
              },
              "createdAt": "2026-10-07T09:12:44.000Z"
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          }
        }
      },
      "get": {
        "tags": [
          "Clients"
        ],
        "operationId": "listClients",
        "summary": "List clients",
        "description": "Lists all your clients and prospects, including those created in the dashboard and on access pages, oldest first. Filter by `externalClientId` to find one client by your own ID, or by `email` (several clients can share an email).",
        "x-scope": "clients:read",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "description": "Results per page, 1-100.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "The `meta.nextCursor` of the previous page. Cursors only work with the filters they were issued for.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "externalClientId",
            "in": "query",
            "description": "Only the client with this external ID (case-sensitive).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "email",
            "in": "query",
            "description": "Only clients with this email (case-insensitive).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of clients.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Client"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            },
            "x-example": [
              {
                "id": "7c1e9f52-3b8a-4d2e-9a61-5f0c2d8b4e17",
                "externalClientId": "crm-4821",
                "name": "Jamie Rivera",
                "email": "jamie@northwindcoffee.com",
                "company": "Northwind Coffee",
                "website": "https://northwindcoffee.com",
                "language": "English",
                "metadata": {
                  "accountManager": "Priya"
                },
                "createdAt": "2026-10-07T09:12:44.000Z"
              }
            ]
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          }
        }
      }
    },
    "/clients/{id}": {
      "get": {
        "tags": [
          "Clients"
        ],
        "operationId": "getClient",
        "summary": "Retrieve a client",
        "x-scope": "clients:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The client ID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The client.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Client"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            },
            "x-example": {
              "id": "7c1e9f52-3b8a-4d2e-9a61-5f0c2d8b4e17",
              "externalClientId": "crm-4821",
              "name": "Jamie Rivera",
              "email": "jamie@northwindcoffee.com",
              "company": "Northwind Coffee",
              "website": "https://northwindcoffee.com",
              "language": "English",
              "metadata": {
                "accountManager": "Priya"
              },
              "createdAt": "2026-10-07T09:12:44.000Z"
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          }
        }
      },
      "patch": {
        "tags": [
          "Clients"
        ],
        "operationId": "updateClient",
        "summary": "Update a client",
        "description": "Changes the fields you send. `externalClientId` can be set on a client that has none; changing an existing one returns `409 EXTERNAL_CLIENT_ID_IMMUTABLE`. Send `null` or an empty string to clear `company` or `website`.",
        "x-scope": "clients:update",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The client ID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClientUpdate"
              },
              "example": {
                "company": "Northwind Coffee Roasters",
                "metadata": {
                  "accountManager": "Sam"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated client.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Client"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            },
            "x-example": {
              "id": "7c1e9f52-3b8a-4d2e-9a61-5f0c2d8b4e17",
              "externalClientId": "crm-4821",
              "name": "Jamie Rivera",
              "email": "jamie@northwindcoffee.com",
              "company": "Northwind Coffee Roasters",
              "website": "https://northwindcoffee.com",
              "language": "English",
              "metadata": {
                "accountManager": "Sam"
              },
              "createdAt": "2026-10-07T09:12:44.000Z"
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          }
        }
      }
    },
    "/requests": {
      "post": {
        "tags": [
          "Requests"
        ],
        "operationId": "createRequest",
        "summary": "Create a request",
        "description": "Creates an access request for a client and returns its `inviteUrl` (to send or link to) and `embedUrl` (to show in an iframe). No email is sent unless `sendEmail` is true. Each request counts once toward your monthly access link allowance (prospects separately); at an enforced limit you get `403 PLAN_LIMIT_REACHED`, and with overage billing extra client links are billed instead. Request at least one service or the intake form.",
        "x-scope": "requests:create",
        "x-idempotent": true,
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "A unique value per create, such as a UUID (1-255 visible ASCII characters). Retrying with the same key and body returns the original result instead of creating another object; keys are kept for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RequestCreate"
              },
              "example": {
                "clientId": "7c1e9f52-3b8a-4d2e-9a61-5f0c2d8b4e17",
                "requestedServices": {
                  "Google Ads": {
                    "accessLevel": "ADMIN",
                    "requestedAccountLinks": [
                      {
                        "internalAccountId": "Xk7pQ2mR9vT4wB8nC3dF6hJ1"
                      }
                    ]
                  },
                  "Meta Ads": {
                    "accessLevel": "['ADVERTISE', 'ANALYZE']",
                    "optional": true,
                    "requestedAccountLinks": [
                      {
                        "internalAccountId": "Lm5sZ8aE2gH6jK9qN3rU7yW4"
                      }
                    ]
                  }
                },
                "intakeForm": {
                  "requested": true
                },
                "redirectUrl": "https://portal.example.com/onboarding/done"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new request.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Request"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            },
            "x-example": {
              "id": "2f6d8a14-91c3-4b7e-a5d0-8e3f1c6b9a72",
              "clientId": "7c1e9f52-3b8a-4d2e-9a61-5f0c2d8b4e17",
              "externalClientId": "crm-4821",
              "status": "pending",
              "stateVersion": 1,
              "source": "api",
              "inviteUrl": "https://acme.agencyaccess.co/i/2f6d8a14-91c3-4b7e-a5d0-8e3f1c6b9a72",
              "embedUrl": "https://acme.agencyaccess.co/i/2f6d8a14-91c3-4b7e-a5d0-8e3f1c6b9a72?mode=embed",
              "intakeForm": {
                "requested": true,
                "complete": false
              },
              "services": [
                {
                  "service": "Google Ads",
                  "platform": "Google",
                  "accessLevel": "ADMIN",
                  "optional": false,
                  "status": "pending",
                  "accounts": [
                    {
                      "internalAccountId": "Xk7pQ2mR9vT4wB8nC3dF6hJ1",
                      "googleAdsMccAccountId": null,
                      "metaBusinessManagerId": null
                    }
                  ],
                  "grantedAssets": []
                },
                {
                  "service": "Meta Ads",
                  "platform": "Meta",
                  "accessLevel": "['ADVERTISE', 'ANALYZE']",
                  "optional": true,
                  "status": "pending",
                  "accounts": [
                    {
                      "internalAccountId": "Lm5sZ8aE2gH6jK9qN3rU7yW4",
                      "googleAdsMccAccountId": null,
                      "metaBusinessManagerId": null
                    }
                  ],
                  "grantedAssets": []
                }
              ],
              "thankYouMessage": null,
              "redirectUrl": "https://portal.example.com/onboarding/done",
              "createdAt": "2026-10-07T09:15:02.000Z",
              "completedAt": null,
              "expiresAt": "2026-10-21T09:15:02.000Z",
              "cancelledAt": null
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          }
        }
      },
      "get": {
        "tags": [
          "Requests"
        ],
        "operationId": "listRequests",
        "summary": "List requests",
        "description": "Lists requests, oldest first. Demo requests are never returned.",
        "x-scope": "requests:read",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "description": "Results per page, 1-100.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "The `meta.nextCursor` of the previous page. Cursors only work with the filters they were issued for.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "clientId",
            "in": "query",
            "description": "Only this client's requests.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "externalClientId",
            "in": "query",
            "description": "Only requests of the client with this external ID.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only requests with this status.",
            "schema": {
              "$ref": "#/components/schemas/RequestStatus"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of requests.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Request"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            },
            "x-example": [
              {
                "id": "2f6d8a14-91c3-4b7e-a5d0-8e3f1c6b9a72",
                "clientId": "7c1e9f52-3b8a-4d2e-9a61-5f0c2d8b4e17",
                "externalClientId": "crm-4821",
                "status": "in_progress",
                "stateVersion": 4,
                "source": "api",
                "inviteUrl": "https://acme.agencyaccess.co/i/2f6d8a14-91c3-4b7e-a5d0-8e3f1c6b9a72",
                "embedUrl": "https://acme.agencyaccess.co/i/2f6d8a14-91c3-4b7e-a5d0-8e3f1c6b9a72?mode=embed",
                "intakeForm": {
                  "requested": true,
                  "complete": false
                },
                "services": [
                  {
                    "service": "Google Ads",
                    "platform": "Google",
                    "accessLevel": "ADMIN",
                    "optional": false,
                    "status": "granted",
                    "accounts": [
                      {
                        "internalAccountId": "Xk7pQ2mR9vT4wB8nC3dF6hJ1",
                        "googleAdsMccAccountId": null,
                        "metaBusinessManagerId": null
                      }
                    ],
                    "grantedAssets": [
                      {
                        "id": "1234567890",
                        "name": "1234567890",
                        "accessLevel": "ADMIN"
                      }
                    ]
                  },
                  {
                    "service": "Meta Ads",
                    "platform": "Meta",
                    "accessLevel": "['ADVERTISE', 'ANALYZE']",
                    "optional": true,
                    "status": "pending",
                    "accounts": [
                      {
                        "internalAccountId": "Lm5sZ8aE2gH6jK9qN3rU7yW4",
                        "googleAdsMccAccountId": null,
                        "metaBusinessManagerId": null
                      }
                    ],
                    "grantedAssets": []
                  }
                ],
                "thankYouMessage": null,
                "redirectUrl": "https://portal.example.com/onboarding/done",
                "createdAt": "2026-10-07T09:15:02.000Z",
                "completedAt": null,
                "expiresAt": "2026-10-21T09:15:02.000Z",
                "cancelledAt": null
              }
            ]
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          }
        }
      }
    },
    "/requests/{id}": {
      "get": {
        "tags": [
          "Requests"
        ],
        "operationId": "getRequest",
        "summary": "Retrieve a request",
        "description": "Returns the request with the status of every requested service and the assets access was granted to. Compare `stateVersion` to tell newer states from older ones.",
        "x-scope": "requests:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The request ID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The request.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Request"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            },
            "x-example": {
              "id": "2f6d8a14-91c3-4b7e-a5d0-8e3f1c6b9a72",
              "clientId": "7c1e9f52-3b8a-4d2e-9a61-5f0c2d8b4e17",
              "externalClientId": "crm-4821",
              "status": "in_progress",
              "stateVersion": 4,
              "source": "api",
              "inviteUrl": "https://acme.agencyaccess.co/i/2f6d8a14-91c3-4b7e-a5d0-8e3f1c6b9a72",
              "embedUrl": "https://acme.agencyaccess.co/i/2f6d8a14-91c3-4b7e-a5d0-8e3f1c6b9a72?mode=embed",
              "intakeForm": {
                "requested": true,
                "complete": false
              },
              "services": [
                {
                  "service": "Google Ads",
                  "platform": "Google",
                  "accessLevel": "ADMIN",
                  "optional": false,
                  "status": "granted",
                  "accounts": [
                    {
                      "internalAccountId": "Xk7pQ2mR9vT4wB8nC3dF6hJ1",
                      "googleAdsMccAccountId": null,
                      "metaBusinessManagerId": null
                    }
                  ],
                  "grantedAssets": [
                    {
                      "id": "1234567890",
                      "name": "1234567890",
                      "accessLevel": "ADMIN"
                    }
                  ]
                },
                {
                  "service": "Meta Ads",
                  "platform": "Meta",
                  "accessLevel": "['ADVERTISE', 'ANALYZE']",
                  "optional": true,
                  "status": "pending",
                  "accounts": [
                    {
                      "internalAccountId": "Lm5sZ8aE2gH6jK9qN3rU7yW4",
                      "googleAdsMccAccountId": null,
                      "metaBusinessManagerId": null
                    }
                  ],
                  "grantedAssets": []
                }
              ],
              "thankYouMessage": null,
              "redirectUrl": "https://portal.example.com/onboarding/done",
              "createdAt": "2026-10-07T09:15:02.000Z",
              "completedAt": null,
              "expiresAt": "2026-10-21T09:15:02.000Z",
              "cancelledAt": null
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          }
        }
      }
    },
    "/requests/{id}/cancel": {
      "post": {
        "tags": [
          "Requests"
        ],
        "operationId": "cancelRequest",
        "summary": "Cancel a request",
        "description": "Stops a request: the client can no longer sign in or grant access through it, and no more reminders can be sent. Sign-ins the client had not finished using are discarded. Access already granted is not revoked. Cancelling a cancelled request is fine; completed or expired requests return `409 INVALID_STATE`.",
        "x-scope": "requests:cancel",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The request ID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The cancelled request.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Request"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            },
            "x-example": {
              "id": "2f6d8a14-91c3-4b7e-a5d0-8e3f1c6b9a72",
              "clientId": "7c1e9f52-3b8a-4d2e-9a61-5f0c2d8b4e17",
              "externalClientId": "crm-4821",
              "status": "cancelled",
              "stateVersion": 5,
              "source": "api",
              "inviteUrl": "https://acme.agencyaccess.co/i/2f6d8a14-91c3-4b7e-a5d0-8e3f1c6b9a72",
              "embedUrl": "https://acme.agencyaccess.co/i/2f6d8a14-91c3-4b7e-a5d0-8e3f1c6b9a72?mode=embed",
              "intakeForm": {
                "requested": true,
                "complete": false
              },
              "services": [
                {
                  "service": "Google Ads",
                  "platform": "Google",
                  "accessLevel": "ADMIN",
                  "optional": false,
                  "status": "granted",
                  "accounts": [
                    {
                      "internalAccountId": "Xk7pQ2mR9vT4wB8nC3dF6hJ1",
                      "googleAdsMccAccountId": null,
                      "metaBusinessManagerId": null
                    }
                  ],
                  "grantedAssets": [
                    {
                      "id": "1234567890",
                      "name": "1234567890",
                      "accessLevel": "ADMIN"
                    }
                  ]
                },
                {
                  "service": "Meta Ads",
                  "platform": "Meta",
                  "accessLevel": "['ADVERTISE', 'ANALYZE']",
                  "optional": true,
                  "status": "pending",
                  "accounts": [
                    {
                      "internalAccountId": "Lm5sZ8aE2gH6jK9qN3rU7yW4",
                      "googleAdsMccAccountId": null,
                      "metaBusinessManagerId": null
                    }
                  ],
                  "grantedAssets": []
                }
              ],
              "thankYouMessage": null,
              "redirectUrl": "https://portal.example.com/onboarding/done",
              "createdAt": "2026-10-07T09:15:02.000Z",
              "completedAt": null,
              "expiresAt": "2026-10-21T09:15:02.000Z",
              "cancelledAt": "2026-10-08T14:30:00.000Z"
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          }
        }
      }
    },
    "/accounts": {
      "get": {
        "tags": [
          "Accounts and services"
        ],
        "operationId": "listAccounts",
        "summary": "List connected accounts",
        "description": "Your agency's connected platform accounts. Use an account's `internalAccountId` in `requestedAccountLinks` to choose which of your accounts the client grants access to.",
        "x-scope": "accounts:read",
        "responses": {
          "200": {
            "description": "All connected accounts.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Account"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            },
            "x-example": [
              {
                "internalAccountId": "Xk7pQ2mR9vT4wB8nC3dF6hJ1",
                "platform": "Google",
                "displayName": "ads@acme.agency",
                "email": "ads@acme.agency",
                "platformAccountId": null,
                "business": null,
                "services": [
                  "Google Ads",
                  "Google Analytics",
                  "Google Tag Manager"
                ],
                "status": "connected",
                "linkedAt": "2026-03-02T11:00:00.000Z"
              }
            ]
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          }
        }
      }
    },
    "/services": {
      "get": {
        "tags": [
          "Accounts and services"
        ],
        "operationId": "listServices",
        "summary": "List services",
        "description": "Every service that can be requested, with its roles. Use a service's `id` as the key in `requestedServices` and one of its role `value`s as `accessLevel` (leave `accessLevel` out when `roles` is empty).",
        "x-scope": "catalog:read",
        "responses": {
          "200": {
            "description": "All services.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Service"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            },
            "x-example": [
              {
                "id": "Google Ads",
                "platform": "Google",
                "roles": [
                  {
                    "value": "ADMIN",
                    "label": "Admin",
                    "readOnly": false
                  },
                  {
                    "value": "STANDARD",
                    "label": "Standard",
                    "readOnly": false
                  },
                  {
                    "value": "READ_ONLY",
                    "label": "Read Only",
                    "readOnly": true
                  },
                  {
                    "value": "EMAIL_ONLY",
                    "label": "Email Only",
                    "readOnly": true
                  }
                ],
                "grantMethod": "automatic",
                "clientSignInRequired": true,
                "accountLinkFields": []
              },
              {
                "id": "Google Ads MCC",
                "platform": "Google",
                "roles": [],
                "grantMethod": "automatic",
                "clientSignInRequired": true,
                "accountLinkFields": [
                  {
                    "name": "googleAdsMccAccountId",
                    "required": true
                  }
                ]
              }
            ]
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          }
        }
      }
    },
    "/usage": {
      "get": {
        "tags": [
          "Usage"
        ],
        "operationId": "getUsage",
        "summary": "Retrieve usage",
        "description": "This month's access link usage (UTC calendar months). Every new request and access page session counts once, clients and prospects separately. A `limit` of null means no limit applies.",
        "x-scope": "usage:read",
        "responses": {
          "200": {
            "description": "Usage for the current month.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Usage"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            },
            "x-example": {
              "plan": "Agency",
              "billingPeriod": "Monthly",
              "trial": false,
              "apiAccess": true,
              "countingMode": "access_links",
              "period": {
                "start": "2026-10-01T00:00:00.000Z",
                "end": "2026-11-01T00:00:00.000Z",
                "timezone": "UTC"
              },
              "clients": {
                "used": 37,
                "limit": 50,
                "remaining": 13
              },
              "prospects": {
                "used": 4,
                "limit": null,
                "remaining": null
              },
              "overage": {
                "enabled": false,
                "included": null,
                "billableUnits": 0
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          }
        }
      }
    },
    "/webhooks": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "createWebhook",
        "summary": "Create a webhook",
        "description": "Registers an endpoint for the event types you choose (`[\"*\"]` for all). The response includes the signing `secret` once; store it to verify deliveries. A retry with the same `Idempotency-Key` returns the webhook without its secret, so if you lost the first response, rotate the secret. Endpoints must use https on port 443 and resolve to public addresses. An agency can have up to 10 webhooks; creating more returns `400 VALIDATION_FAILED`.",
        "x-scope": "webhooks:write",
        "x-idempotent": true,
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "A unique value per create, such as a UUID (1-255 visible ASCII characters). Retrying with the same key and body returns the original result instead of creating another object; keys are kept for 24 hours.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookCreate"
              },
              "example": {
                "url": "https://portal.example.com/hooks/agencyaccess",
                "events": [
                  "request.completed",
                  "service.granted",
                  "service.grant_failed"
                ],
                "description": "Production portal"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new webhook, with its signing secret.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Webhook"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            },
            "x-example": {
              "id": "b81f3c2e-6a4d-4f19-9c7e-0d5a2e8f1b63",
              "url": "https://portal.example.com/hooks/agencyaccess",
              "description": "Production portal",
              "events": [
                "request.completed",
                "service.granted",
                "service.grant_failed"
              ],
              "active": true,
              "previousSecretValidUntil": null,
              "createdAt": "2026-10-07T09:20:00.000Z",
              "updatedAt": "2026-10-07T09:20:00.000Z",
              "secret": "whsec_3kq9Xb7Lw2PzR8vN5tY1cD6hJ0mF4sGaQe7Tu2Wy9Bn"
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          }
        }
      },
      "get": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "listWebhooks",
        "summary": "List webhooks",
        "x-scope": "webhooks:read",
        "responses": {
          "200": {
            "description": "All webhooks (never more than one page).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Webhook"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            },
            "x-example": [
              {
                "id": "b81f3c2e-6a4d-4f19-9c7e-0d5a2e8f1b63",
                "url": "https://portal.example.com/hooks/agencyaccess",
                "description": "Production portal",
                "events": [
                  "request.completed",
                  "service.granted",
                  "service.grant_failed"
                ],
                "active": true,
                "previousSecretValidUntil": null,
                "createdAt": "2026-10-07T09:20:00.000Z",
                "updatedAt": "2026-10-07T09:20:00.000Z"
              }
            ]
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          }
        }
      }
    },
    "/webhooks/{id}": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "getWebhook",
        "summary": "Retrieve a webhook",
        "x-scope": "webhooks:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The webhook ID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The webhook.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Webhook"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            },
            "x-example": {
              "id": "b81f3c2e-6a4d-4f19-9c7e-0d5a2e8f1b63",
              "url": "https://portal.example.com/hooks/agencyaccess",
              "description": "Production portal",
              "events": [
                "request.completed",
                "service.granted",
                "service.grant_failed"
              ],
              "active": true,
              "previousSecretValidUntil": null,
              "createdAt": "2026-10-07T09:20:00.000Z",
              "updatedAt": "2026-10-07T09:20:00.000Z"
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          }
        }
      },
      "patch": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "updateWebhook",
        "summary": "Update a webhook",
        "description": "Changes the URL, events or description, or pauses (`active: false`) and resumes it. Deliveries and retries that come due while it is paused are cancelled, and events that happen while it is paused are never delivered to it. A new URL also applies to pending retries.",
        "x-scope": "webhooks:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The webhook ID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookUpdate"
              },
              "example": {
                "active": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated webhook.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Webhook"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            },
            "x-example": {
              "id": "b81f3c2e-6a4d-4f19-9c7e-0d5a2e8f1b63",
              "url": "https://portal.example.com/hooks/agencyaccess",
              "description": "Production portal",
              "events": [
                "request.completed",
                "service.granted",
                "service.grant_failed"
              ],
              "active": false,
              "previousSecretValidUntil": null,
              "createdAt": "2026-10-07T09:20:00.000Z",
              "updatedAt": "2026-10-08T08:00:00.000Z"
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          }
        }
      },
      "delete": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "deleteWebhook",
        "summary": "Delete a webhook",
        "description": "Deletes the webhook and cancels its pending deliveries. Deleting it again returns 204.",
        "x-scope": "webhooks:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The webhook ID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted."
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          }
        }
      }
    },
    "/webhooks/{id}/rotate-secret": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "rotateWebhookSecret",
        "summary": "Rotate the signing secret",
        "description": "Issues a new signing secret, returned once. For 24 hours deliveries carry a second signature made with the previous secret (`previousSecretValidUntil`), so you can switch without missing events. Rotating again ends the older secret immediately.",
        "x-scope": "webhooks:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The webhook ID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The webhook with its new secret.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Webhook"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            },
            "x-example": {
              "id": "b81f3c2e-6a4d-4f19-9c7e-0d5a2e8f1b63",
              "url": "https://portal.example.com/hooks/agencyaccess",
              "description": "Production portal",
              "events": [
                "request.completed",
                "service.granted",
                "service.grant_failed"
              ],
              "active": true,
              "previousSecretValidUntil": "2026-10-09T08:00:00.000Z",
              "createdAt": "2026-10-07T09:20:00.000Z",
              "updatedAt": "2026-10-08T08:00:00.000Z",
              "secret": "whsec_6YSpsQTSPMWERqf-P4oznCQPRnqegQk6TUd5AwSUE3M"
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          }
        }
      }
    },
    "/webhooks/{id}/test": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "testWebhook",
        "summary": "Send a test event",
        "description": "Sends a `webhook.test` event to the endpoint now (also while it is paused) and returns the delivery with your endpoint's status code or connection error. Failed tests are not retried. Limited to 10 tests a minute per agency.",
        "x-scope": "webhooks:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The webhook ID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The test delivery.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/WebhookDelivery"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            },
            "x-example": {
              "id": "d4a7c1e2-58b9-4f3a-8e6d-2c9b0f1a7e35",
              "eventId": "evt_5b1f0c9a2e7d4c38a6f1d2e9b8c7a604",
              "eventType": "webhook.test",
              "test": true,
              "status": "succeeded",
              "attemptCount": 1,
              "lastAttemptAt": "2026-10-07T10:02:11.000Z",
              "lastStatusCode": 200,
              "lastError": null,
              "nextAttemptAt": null,
              "completedAt": "2026-10-07T10:02:11.000Z",
              "createdAt": "2026-10-07T10:02:10.000Z",
              "attempts": [
                {
                  "id": "a1f9e3c7-2b6d-4e8a-9c0f-5d7b3e1a8f24",
                  "attemptedAt": "2026-10-07T10:02:11.000Z",
                  "durationMs": 184,
                  "statusCode": 200,
                  "error": null
                }
              ]
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          }
        }
      }
    },
    "/webhooks/{id}/deliveries": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "listWebhookDeliveries",
        "summary": "List deliveries",
        "description": "The webhook's deliveries, newest first, each with its recent attempts.",
        "x-scope": "webhooks:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The webhook ID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Results per page, 1-100.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "The `meta.nextCursor` of the previous page. Cursors only work with the filters they were issued for.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only deliveries with this status.",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "succeeded",
                "failed",
                "cancelled"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of deliveries.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookDelivery"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            },
            "x-example": [
              {
                "id": "d4a7c1e2-58b9-4f3a-8e6d-2c9b0f1a7e35",
                "eventId": "evt_5b1f0c9a2e7d4c38a6f1d2e9b8c7a604",
                "eventType": "request.completed",
                "test": false,
                "status": "succeeded",
                "attemptCount": 1,
                "lastAttemptAt": "2026-10-07T10:02:11.000Z",
                "lastStatusCode": 200,
                "lastError": null,
                "nextAttemptAt": null,
                "completedAt": "2026-10-07T10:02:11.000Z",
                "createdAt": "2026-10-07T10:02:10.000Z",
                "attempts": [
                  {
                    "id": "a1f9e3c7-2b6d-4e8a-9c0f-5d7b3e1a8f24",
                    "attemptedAt": "2026-10-07T10:02:11.000Z",
                    "durationMs": 184,
                    "statusCode": 200,
                    "error": null
                  }
                ]
              }
            ]
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "An API key from the dashboard (API section), sent as `Authorization: Bearer aa_live_...`."
      }
    },
    "schemas": {
      "Meta": {
        "type": "object",
        "required": [
          "requestId"
        ],
        "properties": {
          "requestId": {
            "type": "string",
            "description": "Identifies this call; also in the `X-Request-Id` header. Include it when contacting support."
          }
        }
      },
      "PageMeta": {
        "type": "object",
        "required": [
          "requestId",
          "nextCursor"
        ],
        "properties": {
          "requestId": {
            "type": "string",
            "description": "Identifies this call."
          },
          "nextCursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error",
          "meta"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message",
              "details"
            ],
            "properties": {
              "code": {
                "$ref": "#/components/schemas/ErrorCode"
              },
              "message": {
                "type": "string",
                "description": "What went wrong, for people."
              },
              "details": {
                "type": "array",
                "description": "The problems found, when there are any; `field` is left out when none applies.",
                "items": {
                  "type": "object",
                  "properties": {
                    "field": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "message"
                  ]
                }
              }
            }
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      },
      "ErrorCode": {
        "type": "string",
        "enum": [
          "AUTHENTICATION_REQUIRED",
          "INVALID_API_KEY",
          "API_KEY_REVOKED",
          "CAPABILITY_REQUIRED",
          "PLAN_NOT_ENTITLED",
          "PLAN_LIMIT_REACHED",
          "INVALID_STATE",
          "VALIDATION_FAILED",
          "EXTERNAL_CLIENT_ID_CONFLICT",
          "EXTERNAL_CLIENT_ID_IMMUTABLE",
          "IDEMPOTENCY_CONFLICT",
          "IDEMPOTENCY_IN_PROGRESS",
          "NOT_FOUND",
          "RATE_LIMITED",
          "INTERNAL_ERROR"
        ]
      },
      "Me": {
        "type": "object",
        "properties": {
          "agency": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "name": {
                "type": "string"
              }
            }
          },
          "apiKey": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "scopes": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Scope"
                }
              }
            }
          }
        }
      },
      "Scope": {
        "type": "string",
        "enum": [
          "clients:read",
          "clients:create",
          "clients:update",
          "requests:read",
          "requests:create",
          "requests:update",
          "requests:cancel",
          "accounts:read",
          "catalog:read",
          "webhooks:read",
          "webhooks:write",
          "usage:read"
        ]
      },
      "Language": {
        "type": "string",
        "enum": [
          "English",
          "Spanish",
          "Dutch"
        ],
        "description": "The language of the client's pages and emails."
      },
      "Client": {
        "type": "object",
        "required": [
          "id",
          "externalClientId",
          "name",
          "email",
          "company",
          "website",
          "language",
          "metadata",
          "createdAt"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "externalClientId": {
            "type": [
              "string",
              "null"
            ],
            "description": "Your ID for the client, unique within your agency."
          },
          "name": {
            "type": "string",
            "description": "The contact person's name."
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "company": {
            "type": [
              "string",
              "null"
            ]
          },
          "website": {
            "type": [
              "string",
              "null"
            ]
          },
          "language": {
            "$ref": "#/components/schemas/Language"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Your own string values."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ClientCreate": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name",
          "email"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "The contact person's name."
          },
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 320
          },
          "company": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 200,
            "description": "Blank becomes null."
          },
          "website": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 2048,
            "description": "Blank becomes null. Not checked as a URL."
          },
          "language": {
            "$ref": "#/components/schemas/Language",
            "default": "English"
          },
          "metadata": {
            "type": "object",
            "maxProperties": 50,
            "additionalProperties": {
              "type": "string",
              "maxLength": 1000
            },
            "description": "Up to 50 string values (keys up to 100 characters)."
          },
          "externalClientId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "Your ID for the client: unique within your agency, case-sensitive, no surrounding spaces. Cannot be changed once set."
          }
        }
      },
      "ClientUpdate": {
        "type": "object",
        "additionalProperties": false,
        "minProperties": 1,
        "description": "Send only the fields to change.",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 320
          },
          "company": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 200
          },
          "website": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 2048
          },
          "language": {
            "$ref": "#/components/schemas/Language"
          },
          "metadata": {
            "type": "object",
            "maxProperties": 50,
            "additionalProperties": {
              "type": "string",
              "maxLength": 1000
            },
            "description": "Replaces all metadata."
          },
          "externalClientId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "Only when the client has none yet."
          }
        }
      },
      "RequestStatus": {
        "type": "string",
        "enum": [
          "pending",
          "in_progress",
          "completed",
          "cancelled",
          "expired"
        ],
        "description": "`pending`: nothing granted, skipped or submitted yet (opening the link or signing in does not change it). `in_progress`: at least one service is granted or skipped, an invite awaits your confirmation, or the intake form is submitted. `completed`: every service is granted (optional ones may be skipped instead), not every service was skipped, and the intake form, if requested, is submitted. A completed request returns to `in_progress` if you ask for more access. `cancelled` and `expired` are final."
      },
      "Request": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "clientId": {
            "type": "string",
            "format": "uuid"
          },
          "externalClientId": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "$ref": "#/components/schemas/RequestStatus"
          },
          "stateVersion": {
            "type": "integer",
            "description": "Increases with every change; use it to ignore older states and events."
          },
          "source": {
            "type": "string",
            "enum": [
              "api",
              "dashboard",
              "static_link"
            ],
            "description": "Where the request was created."
          },
          "inviteUrl": {
            "type": "string",
            "format": "uri",
            "description": "The link the client opens to grant access."
          },
          "embedUrl": {
            "type": "string",
            "format": "uri",
            "description": "The same link for an iframe in your portal."
          },
          "intakeForm": {
            "type": "object",
            "properties": {
              "requested": {
                "type": "boolean"
              },
              "complete": {
                "type": "boolean"
              }
            }
          },
          "services": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RequestedService"
            }
          },
          "thankYouMessage": {
            "type": [
              "string",
              "null"
            ]
          },
          "redirectUrl": {
            "type": [
              "string",
              "null"
            ],
            "description": "Where the client is sent after finishing."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "completedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "After this, no new grants; the request reports `expired` unless it is already completed or cancelled. Null when the request never expires."
          },
          "cancelledAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "RequestedService": {
        "type": "object",
        "properties": {
          "service": {
            "type": "string",
            "description": "The service ID, such as `Google Ads`."
          },
          "platform": {
            "type": "string",
            "description": "The platform, such as `Google`."
          },
          "accessLevel": {
            "type": [
              "string",
              "null"
            ],
            "description": "The requested role."
          },
          "optional": {
            "type": "boolean",
            "description": "The client may skip it. Optional services still need to be granted or skipped for the request to complete."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "granted",
              "skipped"
            ],
            "description": "Only optional services can be skipped."
          },
          "accounts": {
            "type": "array",
            "description": "Your accounts access is requested for.",
            "items": {
              "type": "object",
              "properties": {
                "internalAccountId": {
                  "type": "string"
                },
                "googleAdsMccAccountId": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "metaBusinessManagerId": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          },
          "grantedAssets": {
            "type": "array",
            "description": "The client's assets access was granted to.",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "description": "The asset's ID on the platform."
                },
                "name": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "accessLevel": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          }
        }
      },
      "RequestCreate": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "clientId"
        ],
        "properties": {
          "clientId": {
            "type": "string",
            "description": "The client to request access from."
          },
          "requestedServices": {
            "type": "object",
            "description": "Services to request, keyed by service ID (see `GET /services`).",
            "additionalProperties": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "accessLevel": {
                  "type": "string",
                  "description": "One of the service's role values; leave out for services without roles."
                },
                "optional": {
                  "type": "boolean",
                  "default": false,
                  "description": "The client may skip it. The request completes once each service is granted, or skipped if optional."
                },
                "requestedAccountLinks": {
                  "type": "array",
                  "maxItems": 50,
                  "description": "Which of your connected accounts (see `GET /accounts`) the client grants access to. Each must be one of your accounts on the service's platform.",
                  "items": {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "internalAccountId"
                    ],
                    "properties": {
                      "internalAccountId": {
                        "type": "string"
                      },
                      "googleAdsMccAccountId": {
                        "type": "string",
                        "description": "Required for Google Ads MCC."
                      },
                      "metaBusinessManagerId": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          },
          "intakeForm": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "requested"
            ],
            "properties": {
              "requested": {
                "type": "boolean"
              }
            },
            "description": "Ask the client to fill in your intake form (it must be enabled with questions)."
          },
          "sendEmail": {
            "type": "boolean",
            "default": false,
            "description": "Email the client the link."
          },
          "thankYouMessage": {
            "type": "string",
            "maxLength": 2000
          },
          "redirectUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "An absolute http(s) URL to send the client to after finishing."
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "A future time, at most a year away, after which the client can no longer grant access. Without it the request never expires."
          }
        }
      },
      "Account": {
        "type": "object",
        "properties": {
          "internalAccountId": {
            "type": "string",
            "description": "Use in `requestedAccountLinks`."
          },
          "platform": {
            "type": "string"
          },
          "displayName": {
            "type": [
              "string",
              "null"
            ]
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "platformAccountId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The account's ID on the platform."
          },
          "business": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "services": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Services this account can receive access to."
          },
          "status": {
            "type": "string",
            "enum": [
              "connected",
              "disconnected"
            ]
          },
          "linkedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Service": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The key to use in `requestedServices`."
          },
          "platform": {
            "type": "string"
          },
          "roles": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "value": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                },
                "readOnly": {
                  "type": "boolean"
                }
              }
            }
          },
          "grantMethod": {
            "type": "string",
            "enum": [
              "automatic",
              "manual"
            ],
            "description": "`manual`: the client follows instructions instead of granting in one click."
          },
          "clientSignInRequired": {
            "type": "boolean",
            "description": "The client signs in with the platform to grant it."
          },
          "accountLinkFields": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                },
                "required": {
                  "type": "boolean"
                }
              }
            },
            "description": "Extra fields each requested account link needs."
          }
        }
      },
      "Usage": {
        "type": "object",
        "properties": {
          "plan": {
            "type": [
              "string",
              "null"
            ]
          },
          "billingPeriod": {
            "type": [
              "string",
              "null"
            ]
          },
          "trial": {
            "type": "boolean"
          },
          "apiAccess": {
            "type": "boolean"
          },
          "countingMode": {
            "type": "string",
            "enum": [
              "access_links"
            ]
          },
          "period": {
            "type": "object",
            "properties": {
              "start": {
                "type": "string",
                "format": "date-time"
              },
              "end": {
                "type": "string",
                "format": "date-time"
              },
              "timezone": {
                "type": "string"
              }
            }
          },
          "clients": {
            "$ref": "#/components/schemas/UsageCounter"
          },
          "prospects": {
            "$ref": "#/components/schemas/UsageCounter"
          },
          "overage": {
            "type": "object",
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "included": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "billableUnits": {
                "type": "integer"
              }
            },
            "description": "With overage billing, client links beyond `included` are billed instead of refused."
          }
        }
      },
      "UsageCounter": {
        "type": "object",
        "properties": {
          "used": {
            "type": "integer"
          },
          "limit": {
            "type": [
              "integer",
              "null"
            ]
          },
          "remaining": {
            "type": [
              "integer",
              "null"
            ]
          }
        }
      },
      "EventType": {
        "type": "string",
        "enum": [
          "client.created",
          "request.created",
          "request.updated",
          "request.completed",
          "request.cancelled",
          "request.expired",
          "service.granted",
          "service.skipped",
          "service.grant_failed",
          "connection.attempt_completed",
          "intake.completed"
        ]
      },
      "Webhook": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Subscribed event types, or `[\"*\"]`."
          },
          "active": {
            "type": "boolean"
          },
          "previousSecretValidUntil": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "After a rotation, the previous secret also signs deliveries until then."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "secret": {
            "type": "string",
            "description": "The signing secret, only when the webhook is created or its secret rotated."
          }
        }
      },
      "WebhookCreate": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "url",
          "events"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "An https URL on port 443 that resolves to public addresses."
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "client.created",
                "request.created",
                "request.updated",
                "request.completed",
                "request.cancelled",
                "request.expired",
                "service.granted",
                "service.skipped",
                "service.grant_failed",
                "connection.attempt_completed",
                "intake.completed",
                "*"
              ]
            },
            "minItems": 1,
            "maxItems": 11,
            "description": "Event types to receive, each once, or `[\"*\"]` on its own for all."
          },
          "description": {
            "type": "string",
            "maxLength": 200
          }
        }
      },
      "WebhookUpdate": {
        "type": "object",
        "additionalProperties": false,
        "minProperties": 1,
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "client.created",
                "request.created",
                "request.updated",
                "request.completed",
                "request.cancelled",
                "request.expired",
                "service.granted",
                "service.skipped",
                "service.grant_failed",
                "connection.attempt_completed",
                "intake.completed",
                "*"
              ]
            },
            "minItems": 1,
            "maxItems": 11
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 200
          },
          "active": {
            "type": "boolean",
            "description": "`false` pauses deliveries."
          }
        }
      },
      "WebhookDelivery": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Also sent as `AgencyAccess-Delivery-Id`; stays the same across retries."
          },
          "eventId": {
            "type": "string"
          },
          "eventType": {
            "type": "string"
          },
          "test": {
            "type": "boolean"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "succeeded",
              "failed",
              "cancelled"
            ]
          },
          "attemptCount": {
            "type": "integer"
          },
          "lastAttemptAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "lastStatusCode": {
            "type": [
              "integer",
              "null"
            ]
          },
          "lastError": {
            "type": [
              "string",
              "null"
            ]
          },
          "nextAttemptAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the next retry is due."
          },
          "completedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "attempts": {
            "type": "array",
            "description": "The 10 most recent attempts, newest first.",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "attemptedAt": {
                  "type": "string",
                  "format": "date-time"
                },
                "durationMs": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "statusCode": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "error": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "responses": {
      "Error400": {
        "description": "The request is invalid (`VALIDATION_FAILED`); `details` lists the problems, with `field` when one applies.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error401": {
        "description": "The API key is missing, invalid or revoked.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error403": {
        "description": "The key lacks the scope (`CAPABILITY_REQUIRED`), the plan has no API access (`PLAN_NOT_ENTITLED`), or, when creating a request, the monthly limit is reached (`PLAN_LIMIT_REACHED`).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error404": {
        "description": "Not found, or it belongs to another agency.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error409": {
        "description": "A conflict: an `externalClientId` in use or immutable, an Idempotency-Key reused with a different body or still in progress, or a request in a state that does not allow this.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error429": {
        "description": "Rate limited (`RATE_LIMITED`); wait for `Retry-After` seconds.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  }
}