# Fincore Webhooks

> This page documents the mechanics of Fincore webhooks: registration, verification, management, retries, and troubleshooting. For the type-specific detail (what's in the `body`, when it fires), see the corresponding section in the main guide: [Receiving money (Money In)](#), [Penny Validation](#), [Reports](#).


## Table of contents

1. What is a webhook in Fincore?
2. Available webhook types
3. Register an endpoint
4. Verify the notification comes from Fincore
5. Managing your webhooks
6. Common envelope
7. Retries
8. Troubleshooting
9. Best practices


## 1. What is a webhook in Fincore?

Fincore uses a single push-notification mechanism to notify you of asynchronous events: money arriving, a Penny Validation CEP becoming ready, or a report file being generated. Instead of repeatedly polling the API, you register a URL once and Fincore notifies you via HTTP POST when something relevant happens.

All three webhook types share the same registration endpoint and general behavior - only the `webhook_type` and the `body` content change.

## 2. Available webhook types

| `webhook_type` | Fires when... | Full detail in... |
|  --- | --- | --- |
| `MONEY_IN` | Money arrives (external SPEI or internal transfer) | Main guide, "Receiving money (Money In)" section |
| `CEP` | A Penny Validation CEP becomes ready (`COMPLETED` or `FAILED`) | Main guide, "Validating a bank account (Penny Validation)" section |
| `REPORT` | A report file (transactions or account statement) is generated | Main guide, "Reports" section |


## 3. Register an endpoint

You tell Fincore which URL to send notifications to. The same endpoint serves all three types - only `webhook_type` changes.

```
POST /v1/clients/{client_id}/webhooks
```

**Body:**

```json
{
  "client_id": "{your clientId}",
  "url": "https://your-server.com/webhook",
  "token": "your-secret-token",
  "webhook_type": "MONEY_IN",
  "auth_type": "AUTH"
}
```

`webhook_type` accepts `"MONEY_IN"`, `"CEP"`, or `"REPORT"`. If you need to listen to all three, register three webhooks (they can point to the same URL, or different ones - you decide how to structure your infrastructure).

**Response (200 OK):**

```json
{
  "id": "0c2d358f-...",
  "webhookType": "MONEY_IN",
  "webhookStatus": "ACTIVE"
}
```

> **Note on format:** the request body uses `snake_case` (e.g. `webhook_type`) but the response uses `camelCase` (e.g. `webhookType`). This is consistent throughout the API.


## 4. Verify the notification comes from Fincore

The `token` field you send when registering the webhook is included in every notification Fincore sends you, so you can verify the request genuinely comes from us and not from a third party.

> **How do I generate a good** `token`**?** We recommend a random secret of at least 32 bytes - for example, a UUID v4, or a SHA-256 hash of a secure random source. Avoid predictable values (your company name, dates, etc.) and store it securely in your backend, just as you would any other authentication secret.


When receiving a notification, compare the received `token` against the one you registered, using a constant-time comparison if your language supports it (to avoid timing attacks), before processing the payload.

## 5. Managing your webhooks

| Action | Method | Endpoint |
|  --- | --- | --- |
| List all | GET | `/v1/clients/{client_id}/webhooks` |
| Get one | GET | `/v1/clients/{client_id}/webhooks/{id}` |
| Create | POST | `/v1/clients/{client_id}/webhooks` |
| Update | PATCH | `/v1/clients/{client_id}/webhooks/{id}` |
| Delete | DELETE | `/v1/clients/{client_id}/webhooks/{id}` |


These five endpoints apply equally to all three types (`MONEY_IN`, `CEP`, `REPORT`) - there are no per-type endpoints.

## 6. Common envelope

> **What is an "envelope"?** This is a common term in API design: the "envelope" that wraps every message, with data common to any notification (who sent it, when, what type it is), regardless of what content it carries inside. It's the same idea as a physical mail envelope: the envelope (sender, date) has the same format no matter what letter is inside it. Here, `id_msg`, `msg_name`, and `msg_date` are the "envelope" - they're always present, regardless of the webhook type. The `body` is the "letter" - its content changes completely depending on whether it's `MONEY_IN`, `CEP`, or `REPORT`.


Every notification, regardless of type, shares this general structure:

```json
{
  "id_msg": "a7a126e8-fa74-411c-ad2b-b000f277bb0d",
  "msg_name": "MONEY_IN",
  "msg_date": "2025-04-02",
  "body": { }
}
```

| Field | Description |
|  --- | --- |
| `id_msg` | Unique ID for this notification - use it to deduplicate (see section 9) |
| `msg_name` | The event type: `MONEY_IN`, `CEP`, or the one corresponding to `REPORT` |
| `msg_date` | Event date |
| `body` | Event-specific content - varies by type, see the corresponding section in the main guide |


## 7. Retries

> **The retry policy is not the same across all three types.** Today only `CEP` has a documented retry policy. `MONEY_IN` and `REPORT` don't currently have a published retry policy.


| Type | Retry policy |
|  --- | --- |
| `CEP` | 37 attempts over a 7h 20min window. The scraper runs in parallel to Penny Validation; the `PENDING`/`DELAYED` statuses are emulated by Monato. See full detail in the Penny Validation section. |
| `MONEY_IN` | Not documented |
| `REPORT` | Not documented |


## 8. Troubleshooting

| Situation | Likely cause | What to do |
|  --- | --- | --- |
| Timeout | Your server took too long to respond | Return a success code immediately, process complex logic afterward, asynchronously |
| Redirect (3xx) | Your endpoint redirects the request to another URL | Fincore doesn't follow redirects - configure the final URL directly, with no redirects |
| 4xx | Your endpoint rejected the request | Check that it accepts POST, has no access restrictions (auth, IP allowlist, etc.), and that the URL exists |
| 5xx | Error in your server while processing the request | Check your application logs |
| Nothing arrives | Your URL isn't publicly reachable, or a firewall is blocking it | Verify the URL is reachable from the internet, with valid HTTPS |


## 9. Best practices

* **Deduplicate by** `id_msg`. You may receive the same notification more than once - store the `id_msg` values you've already processed and skip duplicates.
* **Respond fast, process later.** Return a success code before running complex logic (updating your database, calling other systems). If processing is slow, queue it and process asynchronously.
* **Don't rely on delivery order.** If you register multiple webhook types, don't assume they'll arrive in a specific order.
* **Use HTTPS.** Your endpoint must be publicly accessible over HTTPS with a valid certificate.
* **Verify the** `token` on every request before trusting the payload contents (see section 4).


## Questions or issues?

* **Technical support:** [support@monato.com](mailto:support@monato.com)
* **Main guide:** see "Fincore - Developer Guide (EN)"


*Fincore API - Finco Pay | Monato*