Procurando a documentação anterior?Acesse v1.docs.pluggy.ai
PluggyDocs
Voltar ao guia

Referência da API de Suporte para Parceiros

Todas as operações da API em uma página, geradas a partir do mesmo documento OpenAPI que o seu gerador de código lê.

Envie sua API key como Authorization: Bearer … em todas as requisições.

URL basehttps://docs.pluggy.aiDocumento OpenAPI 3.0 (JSON)

Chamados

GET/api/partners/tickets

List your tickets

Your account's tickets, newest first, with the SLA due date and whether it has been breached.

Parameters

Query Parameters

NameType
limit
integer
cursor
string

Responses

200Your tickets
object
nextCursorstring | nullnullable

Pass as `cursor` to fetch the next page. Null on the last page.

ticketsobject[]
itemsobject

Example response

json
{
  "nextCursor": "string",
  "tickets": [
    {
      "ticket": "SUP2-13826",
      "summary": "string",
      "state": "on_you",
      "itemId": "550e8400-e29b-41d4-a716-446655440000",
      "derivedFromItem": {
        "connectorName": "Itaú",
        "isOpenFinance": true
      },
      "status": "Em Análise",
      "createdAt": "2024-01-01T00:00:00Z",
      "externalId": "YOUR-1947",
      "openedBy": {
        "email": "user@example.com",
        "name": "string"
      },
      "portalUrl": "string",
      "sla": {
        "name": "Primeira Resposta",
        "dueAt": "2024-01-01T00:00:00Z",
        "breached": true
      }
    }
  ]
}
curl -X GET \
'https://docs.pluggy.ai/api/partners/tickets' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_API_KEY'
Resposta de exemplo
{
"nextCursor": "string",
"tickets": [
{
"ticket": "SUP2-13826",
"summary": "string",
"state": "on_you",
"itemId": "550e8400-e29b-41d4-a716-446655440000",
"derivedFromItem": {
"connectorName": "Itaú",
"isOpenFinance": true
},
"status": "Em Análise",
"createdAt": "2024-01-01T00:00:00Z",
"externalId": "YOUR-1947",
"openedBy": {
"email": "user@example.com",
"name": "string"
},
"portalUrl": "string",
"sla": {
"name": "Primeira Resposta",
"dueAt": "2024-01-01T00:00:00Z",
"breached": true
}
}
]
}
POST/api/partners/tickets

Open a support ticket

Request Body

required
object
summaryrequiredstring

Short title. Note the support workflow rewrites it as `[YourOrg/Institution] problem (externalId)`, so keep it descriptive but don't rely on it.

descriptionrequiredstring

What is wrong, since when, how many users are affected, and how to reproduce. This is what the support engineer reads first.

itemIdrequiredstring (uuid)

The Pluggy item where the problem reproduces. It must belong to your account, and its connector is what determines the institution and whether the case is Open Finance — you don't send those.

productrequiredstring
IdentityAccountsTransactionsCredit CardInvestmentsAuthenticationInvestment TransactionsConsentLoansOutro
problemTyperequiredstring
Transação da conta corrente não sendo retornadaBalanço da conta corrente sendo retornada incorretamenteData da transação da conta corrente sendo retornada incorretamenteCampo recebedor e pagador não está sendo retornados (paymentdata)Transação da conta corrente sendo retornada duplicadaTransação do cartão de credito não sendo retornadaCompras parceladas sendo retornadas incorretamenteConexão não esta sendo atualizada automaticamenteTransação do cartão de crédito sendo retornada duplicadaTransação do investimento não sendo retornadaCNPJ do investimento não sendo retornadaBalanço do investimento sendo retornado incorretamenteInvestimentos sendo retornados com um status incorretoInvestimento sendo retornado sem o campo valueInvestimento sendo retornado sem o campo quantityInvestimentos sendo retornados com dados incorretosIdentity não sendo retornadaErro no consentimentoConexão retornada com o status de PARTIAL_SUCCESSConta corrente não sendo retornadaCartão de credito não sendo retornadoInvestimento não retornadoOutro
accountTypestring
Pessoa FísicaPessoa JurídicaCorretoraOutra

Default: "Outra"

accountIdstring

Pluggy account id, when relevant.

investmentIdstring

Pluggy investment id, when relevant.

externalIdstring

Your own issue id (e.g. a Linear key). Idempotency key: retrying with the same value returns the existing open ticket instead of creating a duplicate.

openedByobject

Who on your side opened this. We add them as a participant on the ticket and name them in the description, so a second analyst opening the same thing can see it is already taken. It does NOT change the reporter — that stays your account's contact.

emailrequiredstring (email)
namestring

Used the first time we see this address, to name the portal contact.

prioritystring
P0 — CríticoP1 — AltoP2 — MédioP3 — Baixo
attachmentsobject[]
itemsobject

Evidence: screenshots, HAR files, logs. Provide either `url` (preferred — we download it) or inline `base64`. Max 10 MB per file, 5 files per ticket.

dryRunboolean

Validate and return the payload we would file, without creating a ticket. Does not count against your quota.

Example

json
{
  "summary": "Transação do cartão de crédito não sendo retornada",
  "description": "Item conectado e atualizado, fatura fechada em 05/08. As 3 últimas transações não aparecem na API. Afeta ~40 usuários desde 04/08.",
  "itemId": "8f2a1b3c-0000-4d4e-9a9a-111122223333",
  "product": "Credit Card",
  "problemType": "Transação do cartão de credito não sendo retornada",
  "accountType": "Pessoa Física",
  "externalId": "YOUR-1947",
  "openedBy": {
    "email": "ana@yourcompany.com",
    "name": "Ana Souza"
  },
  "priority": "P1 — Alto",
  "attachments": [
    {
      "filename": "evidencia.har",
      "contentType": "application/json",
      "url": "https://files.example.com/signed/evidencia.har"
    }
  ]
}

Responses

200No new ticket: either a dry run, or an open ticket already carried this externalId (see `deduplicatedFrom`)
object
ticketstring | nullnullable
portalUrlstring (uri) | nullnullable
statusstring | nullnullable
createdboolean
deduplicatedFromstring | nullnullable

Set when this externalId already had an open ticket.

openedByobject

Echoed when you sent `openedBy`, with what became of them. `added`: they are a participant on the ticket. `failed`: the ticket was filed but we could not attach them — nobody on your side is subscribed, so treat it as not notified. `not_attempted`: there was no new ticket to attach anyone to (a `dryRun`, or a retry that returned an existing ticket).

emailstring (email)
namestring
participantstring
addedfailednot_attempted
attachmentsUploadedinteger
attachmentsFailedinteger

Present only when some files did not land.

attachmentErrorsobject[]

Present only when some files did not land: one entry per file, with the reason.

itemsobject

A file we could not attach, and why.

derivedFromItemobject

What we read from the item: its connector and whether it is Open Finance.

connectorNamestring
isOpenFinanceboolean
unmappedValuesobject[]

Labels we could not map to the intake form. The ticket was still created, with the value preserved in the description.

itemsobject

Example response

json
{
  "ticket": "SUP2-13826",
  "portalUrl": "string",
  "status": "string",
  "created": true,
  "deduplicatedFrom": "string",
  "openedBy": {
    "email": "user@example.com",
    "name": "string",
    "participant": "added"
  },
  "attachmentsUploaded": 0,
  "attachmentsFailed": 0,
  "attachmentErrors": [
    {
      "filename": "extrato.pdf",
      "reason": "Download failed: HTTP 403"
    }
  ],
  "derivedFromItem": {
    "connectorName": "Itaú",
    "isOpenFinance": true
  },
  "unmappedValues": [
    {
      "field": "string",
      "value": "string"
    }
  ]
}
curl -X POST \
'https://docs.pluggy.ai/api/partners/tickets' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-d '{ "summary": "Transação do cartão de crédito não sendo retornada", "description": "Item conectado e atualizado, fatura fechada em 05/08. As 3 últimas transações não aparecem na API. Afeta ~40 usuários desde 04/08.", "itemId": "8f2a1b3c-0000-4d4e-9a9a-111122223333", "product": "Credit Card", "problemType": "Transação do cartão de credito não sendo retornada", "accountType": "Pessoa Física", "externalId": "YOUR-1947", "openedBy": { "email": "ana@yourcompany.com", "name": "Ana Souza" }, "priority": "P1 — Alto", "attachments": [ { "filename": "evidencia.har", "contentType": "application/json", "url": "https://files.example.com/signed/evidencia.har" } ] }'
Resposta de exemplo
{
"ticket": "SUP2-13826",
"portalUrl": "string",
"status": "string",
"created": true,
"deduplicatedFrom": "string",
"openedBy": {
"email": "user@example.com",
"name": "string",
"participant": "added"
},
"attachmentsUploaded": 0,
"attachmentsFailed": 0,
"attachmentErrors": [
{
"filename": "extrato.pdf",
"reason": "Download failed: HTTP 403"
}
],
"derivedFromItem": {
"connectorName": "Itaú",
"isOpenFinance": true
},
"unmappedValues": [
{
"field": "string",
"value": "string"
}
]
}
GET/api/partners/tickets/{key}/comments

Read a ticket's conversation

The messages on one of your tickets, oldest first: our replies and your own, the same conversation your team sees in the support portal. **Only public messages are returned.** Our support team also keeps internal notes on tickets; those are never part of this response. Up to the 200 most recent messages. When a ticket has more, you get the latest 200 and `truncated: true`. A read: it does not count against your monthly ticket quota.

Parameters

Path Parameters

NameType
keyrequired
string

Responses

200The ticket's public messages, oldest first
object
ticketrequiredstring
commentsrequiredobject[]
itemsobject

One public message on a ticket.

truncatedrequiredboolean

True when older messages may have been left out: the ticket has more than 200, or its history is too long to read to the end (1,000 entries, notes included). The most recent messages are always the ones returned.

Example response

json
{
  "ticket": "SUP2-13826",
  "comments": [
    {
      "id": "10001",
      "createdAt": "2026-10-20T16:02:11.000Z",
      "author": {
        "type": "partner",
        "name": "Ana Souza"
      },
      "body": "string"
    }
  ],
  "truncated": true
}
curl -X GET \
'https://docs.pluggy.ai/api/partners/tickets/{key}/comments' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_API_KEY'
Resposta de exemplo
{
"ticket": "SUP2-13826",
"comments": [
{
"id": "10001",
"createdAt": "2026-10-20T16:02:11.000Z",
"author": {
"type": "partner",
"name": "Ana Souza"
},
"body": "string"
}
],
"truncated": true
}
POST/api/partners/tickets/{key}/comments

Follow up on a ticket

Adds a PUBLIC comment to one of your tickets — the same thing your team would write in the portal, so support sees it in the conversation. Filed under your account's portal contact. Does not count against your monthly ticket quota. **Attach evidence after the ticket was opened** with `attachments` — same shape and limits as on the create: up to 5 files, 10 MB each, by `url` or inline `base64`. Send `body`, `attachments`, or both; at least one is required. When files land, the comment lists their names; files with no `body` are posted as a short comment naming them, so support sees the evidence arrive in the conversation. Each file is uploaded on its own: one that cannot be downloaded or uploaded does not stop the others or the comment, and is reported back in `attachmentErrors`. Only when every file failed and there is no `body` is nothing posted — you get a `502` with the reasons.

Parameters

Path Parameters

NameType
keyrequired
string

Request Body

required
object

At least one of `body` and `attachments`.

bodystring

The message. Optional when you send at least one attachment.

attachmentsobject[]
itemsobject

Evidence: screenshots, HAR files, logs. Provide either `url` (preferred — we download it) or inline `base64`. Max 10 MB per file, 5 files per ticket.

Example

json
{
  "body": "O problema voltou a acontecer hoje em 12 usuários."
}

Responses

201Comment added. Check `attachmentsFailed` / `attachmentErrors`: a file that did not land does not fail the call.
object
ticketstring
statusstring | nullnullable
commentedboolean
attachmentsSentinteger

How many files you sent.

attachmentsUploadedinteger

How many landed on the ticket.

attachmentsFailedinteger

Present only when some files did not land: `attachmentsSent - attachmentsUploaded`.

attachmentErrorsobject[]

One entry per file that did not land. Empty when every file landed.

itemsobject

A file we could not attach, and why.

Example response

json
{
  "ticket": "SUP2-13826",
  "status": "Aguardando Time Suporte",
  "commented": true,
  "attachmentsSent": 0,
  "attachmentsUploaded": 0,
  "attachmentsFailed": 0,
  "attachmentErrors": [
    {
      "filename": "extrato.pdf",
      "reason": "Download failed: HTTP 403"
    }
  ]
}
curl -X POST \
'https://docs.pluggy.ai/api/partners/tickets/{key}/comments' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-d '{ "body": "O problema voltou a acontecer hoje em 12 usuários." }'
Resposta de exemplo
{
"ticket": "SUP2-13826",
"status": "Aguardando Time Suporte",
"commented": true,
"attachmentsSent": 0,
"attachmentsUploaded": 0,
"attachmentsFailed": 0,
"attachmentErrors": [
{
"filename": "extrato.pdf",
"reason": "Download failed: HTTP 403"
}
]
}
GET/api/partners/tickets/{key}/events

Read a ticket's history

The timeline of one of your tickets, oldest first: when it was opened, every status, priority and deadline change, every public message, and its resolution — each with its date and who made it. **The event names are the webhook's** (`ticket.status_changed`, `ticket.priority_changed`, `ticket.message_added`, `ticket.resolved`), so a delivery your endpoint missed can be reconciled against this list. `ticket.created` and `ticket.sla_changed` exist only here. Only the changes listed above are returned. Internal notes, and any other change on the ticket, are not. A read: it does not count against your monthly ticket quota.

Parameters

Path Parameters

NameType
keyrequired
string

Responses

200The ticket's history, oldest first
object
ticketrequiredstring
eventsrequiredobject[]
itemsobject

One entry in a ticket's history.

truncatedrequiredboolean

True when this history is incomplete: older messages were left out (as on `GET …/comments`, the 200 most recent are kept), or the ticket's change log is longer than this endpoint reads (only its oldest 2,000 entries are read).

Example response

json
{
  "ticket": "SUP2-13826",
  "events": [
    {
      "type": "ticket.created",
      "at": "2026-10-20T15:58:40.000Z",
      "actor": null,
      "from": null,
      "to": null
    },
    {
      "type": "ticket.status_changed",
      "at": "2026-10-20T16:01:02.000Z",
      "actor": "pluggy",
      "from": "Aguardando Time Suporte",
      "to": "Em análise"
    },
    {
      "type": "ticket.message_added",
      "at": "2026-10-20T16:02:11.000Z",
      "actor": "pluggy",
      "from": null,
      "to": null,
      "message": {
        "id": "10001",
        "createdAt": "2026-10-20T16:02:11.000Z",
        "author": {
          "type": "pluggy",
          "name": "Ana Souza"
        },
        "body": "Olá! Já estamos analisando os itens enviados."
      }
    },
    {
      "type": "ticket.sla_changed",
      "at": "2026-10-21T12:15:00.000Z",
      "actor": "pluggy",
      "from": null,
      "to": "2026-10-30"
    },
    {
      "type": "ticket.resolved",
      "at": "2026-10-29T20:40:00.000Z",
      "actor": "pluggy",
      "from": null,
      "to": "Done"
    }
  ],
  "truncated": false
}
curl -X GET \
'https://docs.pluggy.ai/api/partners/tickets/{key}/events' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_API_KEY'
Resposta de exemplo
{
"ticket": "SUP2-13826",
"events": [
{
"type": "ticket.created",
"at": "2026-10-20T15:58:40.000Z",
"actor": null,
"from": null,
"to": null
},
{
"type": "ticket.status_changed",
"at": "2026-10-20T16:01:02.000Z",
"actor": "pluggy",
"from": "Aguardando Time Suporte",
"to": "Em análise"
},
{
"type": "ticket.message_added",
"at": "2026-10-20T16:02:11.000Z",
"actor": "pluggy",
"from": null,
"to": null,
"message": {
"id": "10001",
"createdAt": "2026-10-20T16:02:11.000Z",
"author": {
"type": "pluggy",
"name": "Ana Souza"
},
"body": "Olá! Já estamos analisando os itens enviados."
}
},
{
"type": "ticket.sla_changed",
"at": "2026-10-21T12:15:00.000Z",
"actor": "pluggy",
"from": null,
"to": "2026-10-30"
},
{
"type": "ticket.resolved",
"at": "2026-10-29T20:40:00.000Z",
"actor": "pluggy",
"from": null,
"to": "Done"
}
],
"truncated": false
}
GET/api/partners/tickets/{key}

Get a ticket's status and SLA

Parameters

Path Parameters

NameType
keyrequired
string

Responses

200Ticket status
object
ticketstring
summarystring
statestring | nullnullable

The coarse lifecycle bucket — the same value the webhooks send. Match on this, not on `status`, which is display text. Null only if we have not mirrored the ticket yet.

newon_youon_customeron_holdclosed
itemIdstring (uuid) | nullnullable

The item the ticket is about, for tickets opened through the API and in the portal alike. Only the organization that owns the ticket reads it: on a ticket shared by several organizations that was opened in the portal it is null for all of them. Also null for a few minutes after a portal ticket is opened (we read the form asynchronously), and on payment tickets, which have no item.

derivedFromItemobject | nullnullable

The connector behind `itemId` and whether it is Open Finance. Same ownership and timing rules as `itemId`; null whenever `itemId` is.

connectorNamestring
isOpenFinanceboolean
statusstring
createdAtstring (date-time)
externalIdstring | nullnullable

The `externalId` you sent when you opened it — your id, handed back so you can join this ticket to your own record without parsing the title. Null on a ticket opened without one, on tickets opened before 2026-10-02, and on a ticket another organization opened and shares with you — it is theirs, not yours.

openedByobject | nullnullable

The `openedBy` you sent when you opened it. Null when you sent none, on tickets opened before 2026-10-02, and on a ticket another organization opened and shares with you.

emailstring (email)
namestring
portalUrlstring (uri)
slaobject[]
itemsobject

Example response

json
{
  "ticket": "SUP2-13826",
  "summary": "string",
  "state": "on_you",
  "itemId": "550e8400-e29b-41d4-a716-446655440000",
  "derivedFromItem": {
    "connectorName": "Itaú",
    "isOpenFinance": true
  },
  "status": "Em Análise",
  "createdAt": "2024-01-01T00:00:00Z",
  "externalId": "YOUR-1947",
  "openedBy": {
    "email": "user@example.com",
    "name": "string"
  },
  "portalUrl": "string",
  "sla": [
    {
      "name": "Primeira Resposta",
      "breached": true,
      "remaining": "6h"
    }
  ]
}
curl -X GET \
'https://docs.pluggy.ai/api/partners/tickets/{key}' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_API_KEY'
Resposta de exemplo
{
"ticket": "SUP2-13826",
"summary": "string",
"state": "on_you",
"itemId": "550e8400-e29b-41d4-a716-446655440000",
"derivedFromItem": {
"connectorName": "Itaú",
"isOpenFinance": true
},
"status": "Em Análise",
"createdAt": "2024-01-01T00:00:00Z",
"externalId": "YOUR-1947",
"openedBy": {
"email": "user@example.com",
"name": "string"
},
"portalUrl": "string",
"sla": [
{
"name": "Primeira Resposta",
"breached": true,
"remaining": "6h"
}
]
}

Webhooks

GET/api/partners/webhooks

List your webhook endpoints

Every endpoint registered for your account, the ticket events each enabled one receives, and whether ticket events can be delivered to your account at all. Signing secrets are never returned here — only when an endpoint is created or its secret is renewed. Does not count against your monthly ticket quota.

Responses

200Your endpoints
object
endpointsrequiredobject[]
itemsobject

One destination for your ticket events. Never carries its signing secret.

eventsrequiredstring[]

The ticket events sent to every enabled endpoint. `webhook.test` is not listed: it is only ever sent when you ask for it.

itemsstring
ticket.status_changedticket.resolvedticket.message_addedticket.priority_changedticket.updated
routedrequiredboolean

Whether ticket events can be delivered to your account. When false, your endpoints are saved but receive nothing until we finish setting up your account — `warning` says so.

warningstring

Present only when `routed` is false.

Example response

json
{
  "endpoints": [
    {
      "id": "3f0b8c1e-6a2d-4c3b-9e1f-2a7d5b8c9e01",
      "url": "https://hooks.yourcompany.com/pluggy/tickets",
      "description": "production",
      "enabled": true,
      "secretRotatedAt": "2026-10-27T12:00:00.000Z",
      "createdAt": "2026-10-27T12:00:00.000Z",
      "updatedAt": "2026-10-27T12:00:00.000Z"
    }
  ],
  "events": [
    "ticket.status_changed",
    "ticket.resolved",
    "ticket.message_added",
    "ticket.priority_changed",
    "ticket.updated"
  ],
  "routed": true
}
curl -X GET \
'https://docs.pluggy.ai/api/partners/webhooks' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_API_KEY'
Resposta de exemplo
{
"endpoints": [
{
"id": "3f0b8c1e-6a2d-4c3b-9e1f-2a7d5b8c9e01",
"url": "https://hooks.yourcompany.com/pluggy/tickets",
"description": "production",
"enabled": true,
"secretRotatedAt": "2026-10-27T12:00:00.000Z",
"createdAt": "2026-10-27T12:00:00.000Z",
"updatedAt": "2026-10-27T12:00:00.000Z"
}
],
"events": [
"ticket.status_changed",
"ticket.resolved",
"ticket.message_added",
"ticket.priority_changed",
"ticket.updated"
],
"routed": true
}
POST/api/partners/webhooks

Register a webhook endpoint

Registers an HTTPS endpoint for your ticket events and returns its signing secret. **The secret is in this response and nowhere else.** It cannot be read back later; if it is lost, renew it with `PATCH` (`rotateSecret: true`). The URL must be `https`, without credentials or a `#fragment`, at most 2048 characters, and on a public host name: IP addresses, `localhost` and private or internal names are refused. Up to 10 endpoints per account, and each URL once. A new endpoint is enabled unless you send `enabled: false`. Send it a `webhook.test` with `POST /api/partners/webhooks/{id}/test` before relying on it. Does not count against your monthly ticket quota.

Request Body

required
object
urlrequiredstring (uri)

`https` only, no credentials, no `#fragment`, on a public host name (not an IP address, `localhost` or an internal name).

descriptionstring | nullnullable
enabledboolean

Send `false` to register it switched off, test it, and enable it later.

Default: true

Example

json
{
  "url": "https://hooks.yourcompany.com/pluggy/tickets",
  "description": "homologação",
  "enabled": false
}

Responses

201Endpoint registered. Store `secret` now. The response is sent with `Cache-Control: no-store`.
object
endpointrequiredobject

One destination for your ticket events. Never carries its signing secret.

idrequiredstring (uuid)
urlrequiredstring (uri)

Where we `POST` the events, normalised as we stored it.

descriptionrequiredstring | nullnullable

Your label for it — the environment or the system that consumes it.

enabledrequiredboolean

Whether ticket events are sent to it. A disabled endpoint receives nothing.

secretRotatedAtrequiredstring (date-time)

When its current signing secret was issued.

createdAtrequiredstring (date-time)
updatedAtrequiredstring (date-time)
secretrequiredstring

The endpoint's signing secret: the HMAC-SHA256 key for `X-Pluggy-Signature`. Returned only when it is issued, and never again.

routedrequiredboolean

Whether ticket events can be delivered to your account. When false, your endpoints are saved but receive nothing until we finish setting up your account — `warning` says so.

warningstring

Present only when `routed` is false.

Example response

json
{
  "endpoint": {
    "id": "3f0b8c1e-6a2d-4c3b-9e1f-2a7d5b8c9e01",
    "url": "https://hooks.yourcompany.com/pluggy/tickets",
    "description": "production",
    "enabled": true,
    "secretRotatedAt": "2024-01-01T00:00:00Z",
    "createdAt": "2024-01-01T00:00:00Z",
    "updatedAt": "2024-01-01T00:00:00Z"
  },
  "secret": "whsec_8c1f0e5a3b9d4c7e2f6a1b0c9d8e7f6a5b4c3d2e1f0a9b8c7d6e5f4a3b2c1d0e",
  "routed": true,
  "warning": "Endpoints are saved, but ticket events cannot be delivered to this account yet — contact Pluggy support."
}
curl -X POST \
'https://docs.pluggy.ai/api/partners/webhooks' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-d '{ "url": "https://hooks.yourcompany.com/pluggy/tickets", "description": "homologação", "enabled": false }'
Resposta de exemplo
{
"endpoint": {
"id": "3f0b8c1e-6a2d-4c3b-9e1f-2a7d5b8c9e01",
"url": "https://hooks.yourcompany.com/pluggy/tickets",
"description": "production",
"enabled": true,
"secretRotatedAt": "2024-01-01T00:00:00Z",
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
},
"secret": "whsec_8c1f0e5a3b9d4c7e2f6a1b0c9d8e7f6a5b4c3d2e1f0a9b8c7d6e5f4a3b2c1d0e",
"routed": true,
"warning": "Endpoints are saved, but ticket events cannot be delivered to this account yet — contact Pluggy support."
}
GET/api/partners/webhooks/{id}

Get a webhook endpoint

One of your endpoints. Its signing secret is never returned here.

Parameters

Path Parameters

NameType
idrequired
string (uuid)

Responses

200The endpoint
object
endpointrequiredobject

One destination for your ticket events. Never carries its signing secret.

idrequiredstring (uuid)
urlrequiredstring (uri)

Where we `POST` the events, normalised as we stored it.

descriptionrequiredstring | nullnullable

Your label for it — the environment or the system that consumes it.

enabledrequiredboolean

Whether ticket events are sent to it. A disabled endpoint receives nothing.

secretRotatedAtrequiredstring (date-time)

When its current signing secret was issued.

createdAtrequiredstring (date-time)
updatedAtrequiredstring (date-time)

Example response

json
{
  "endpoint": {
    "id": "3f0b8c1e-6a2d-4c3b-9e1f-2a7d5b8c9e01",
    "url": "https://hooks.yourcompany.com/pluggy/tickets",
    "description": "production",
    "enabled": true,
    "secretRotatedAt": "2024-01-01T00:00:00Z",
    "createdAt": "2024-01-01T00:00:00Z",
    "updatedAt": "2024-01-01T00:00:00Z"
  }
}
curl -X GET \
'https://docs.pluggy.ai/api/partners/webhooks/{id}' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_API_KEY'
Resposta de exemplo
{
"endpoint": {
"id": "3f0b8c1e-6a2d-4c3b-9e1f-2a7d5b8c9e01",
"url": "https://hooks.yourcompany.com/pluggy/tickets",
"description": "production",
"enabled": true,
"secretRotatedAt": "2024-01-01T00:00:00Z",
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
}
PATCH/api/partners/webhooks/{id}

Update a webhook endpoint or renew its secret

Changes any of `url`, `description` and `enabled`. Send only the fields you want to change. **Renewing the secret:** `rotateSecret: true` issues a new signing secret, and so does sending `url` — even the same URL it already has. The new secret is returned in `secret` (only then), with `Cache-Control: no-store`, and replaces the old one immediately: deliveries from that moment on are signed with it, so update your side right away. Changing `description` or `enabled` keeps the current secret, and the response has no `secret`. A disabled endpoint receives no ticket events. Events that happen while it is disabled are not kept for it.

Parameters

Path Parameters

NameType
idrequired
string (uuid)

Request Body

required
object

At least one field. Unknown fields are refused.

urlstring (uri)

The new URL, under the same rules as on registration. **Always issues a new secret**, even when it is the URL the endpoint already has.

descriptionstring | nullnullable

`null` clears it.

enabledboolean
rotateSecretboolean

`true` issues a new signing secret, which replaces the current one immediately.

Example

json
{
  "rotateSecret": true
}

Responses

200The endpoint as it is now, and `secret` when a new one was issued
object
endpointrequiredobject

One destination for your ticket events. Never carries its signing secret.

idrequiredstring (uuid)
urlrequiredstring (uri)

Where we `POST` the events, normalised as we stored it.

descriptionrequiredstring | nullnullable

Your label for it — the environment or the system that consumes it.

enabledrequiredboolean

Whether ticket events are sent to it. A disabled endpoint receives nothing.

secretRotatedAtrequiredstring (date-time)

When its current signing secret was issued.

createdAtrequiredstring (date-time)
updatedAtrequiredstring (date-time)
secretobject

Present only when this call issued a new secret (`rotateSecret: true`, or `url` sent).

All of:
part 1string

The endpoint's signing secret: the HMAC-SHA256 key for `X-Pluggy-Signature`. Returned only when it is issued, and never again.

Example response

json
{
  "endpoint": {
    "id": "3f0b8c1e-6a2d-4c3b-9e1f-2a7d5b8c9e01",
    "url": "https://hooks.yourcompany.com/pluggy/tickets",
    "description": "production",
    "enabled": true,
    "secretRotatedAt": "2024-01-01T00:00:00Z",
    "createdAt": "2024-01-01T00:00:00Z",
    "updatedAt": "2024-01-01T00:00:00Z"
  },
  "secret": null
}
curl -X PATCH \
'https://docs.pluggy.ai/api/partners/webhooks/{id}' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-d '{ "rotateSecret": true }'
Resposta de exemplo
{
"endpoint": {
"id": "3f0b8c1e-6a2d-4c3b-9e1f-2a7d5b8c9e01",
"url": "https://hooks.yourcompany.com/pluggy/tickets",
"description": "production",
"enabled": true,
"secretRotatedAt": "2024-01-01T00:00:00Z",
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
},
"secret": null
}
DELETE/api/partners/webhooks/{id}

Remove a webhook endpoint

Removes the endpoint. Deliveries still waiting to be retried to it are dropped. To pause deliveries without losing the endpoint and its secret, `PATCH` it with `enabled: false` instead.

Parameters

Path Parameters

NameType
idrequired
string (uuid)

Responses

204Removed
curl -X DELETE \
'https://docs.pluggy.ai/api/partners/webhooks/{id}' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_API_KEY'
POST/api/partners/webhooks/{id}/test

Send a test event to a webhook endpoint

Sends one `webhook.test` event (see `WebhookTestEvent`) to the endpoint now, signed exactly like a ticket event, and tells you what came back. Works on a disabled endpoint too, so you can validate it before switching it on. It is sent once: not retried and not queued. Redirects are not followed — a `3xx` counts as not delivered — and we wait 8 seconds for an answer, the same as for ticket events. The call answers `200` whether or not your endpoint accepted the event; `delivered`, `responseCode` and `error` say how it went.

Parameters

Path Parameters

NameType
idrequired
string (uuid)

Responses

200The attempt was made
object
deliveredrequiredboolean

True when your endpoint answered a 2xx.

responseCoderequiredinteger | nullnullable

The HTTP status your endpoint answered; null when no answer arrived.

errorrequiredstring | nullnullable

Why it was not delivered — a status, a timeout, a connection error. Null when delivered.

eventIdrequiredstring (uuid)

The `eventId` of the test event we sent, so you can find it in your logs.

durationMsrequiredinteger

How long the attempt took.

Example response

json
{
  "delivered": true,
  "responseCode": 200,
  "error": null,
  "eventId": "550e8400-e29b-41d4-a716-446655440000",
  "durationMs": 143
}
curl -X POST \
'https://docs.pluggy.ai/api/partners/webhooks/{id}/test' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_API_KEY'
Resposta de exemplo
{
"delivered": true,
"responseCode": 200,
"error": null,
"eventId": "550e8400-e29b-41d4-a716-446655440000",
"durationMs": 143
}