Webhooks allow you to receive real-time notifications whenever events occur in your workspace, such as payments received, transfers completed, or boletos paid.
Instead of polling the API for updates, you register a URL and Stark Bank will send a POST request to it every time a relevant event happens.
Every webhook event is signed with a digital signature that our SDKs verify automatically, ensuring the authenticity of each notification.
Below you will learn how to subscribe to events, handle them securely, and build a resilient integration.
NOTE: Read Core Concepts before continuing this guide.
A Webhook subscription tells Stark Bank where to send event notifications. You provide an HTTPS URL and a list of event types you want to receive.
Your endpoint must use a valid TLS/SSL certificate — self-signed certificates are not supported.
Available subscriptions: deposit, invoice, brcode-payment, transfer, utility-payment, boleto, boleto-payment, darf-payment, payment-request, boleto-holmes.
Subscribe only to the event types your application needs. This reduces unnecessary traffic and simplifies your event handler.
Register a new webhook by providing your endpoint URL and the event types you want to subscribe to.
You can subscribe to one or more event types at once. Each webhook will only receive events for the subscriptions you specify.
import starkbank
webhook = starkbank.webhook.create(
url="https://winterfell.westeros.gov/events-from-stark-bank",
subscriptions=[
"boleto",
"boleto-payment",
"transfer",
"utility-payment"
]
)
print(webhook)
const starkbank = require('starkbank');
(async() => {
let webhook = await starkbank.webhook.create({
url: 'https://winterfell.westeros.gov/events-from-stark-bank',
subscriptions: ['transfer', 'boleto', 'boleto-payment', 'utility-payment'],
});
console.log(webhook);
})();
$webhook = StarkBank\Webhook::create([
"url" => "https://winterfell.westeros.gov/events-from-stark-bank",
"subscriptions" => ["boleto", "boleto-payment", "transfer", "utility-payment"]
]);
print_r($webhook);
import com.starkbank.*;
import java.util.HashMap;
HashMap<String, Object> data = new HashMap<>();
data.put("url", "https://winterfell.westeros.gov/events-from-stark-bank");
data.put("subscriptions", new String[]{"boleto", "boleto-payment", "transfer", "utility-payment"});
Webhook webhook = Webhook.create(data);
System.out.println(webhook);
require('starkbank')
webhook = StarkBank::Webhook.create(
url: 'https://winterfell.westeros.gov/events-from-stark-bank',
subscriptions: %w[boleto boleto-payment transfer utility-payment]
)
puts webhook
webhook = StarkBank.Webhook.create!(
url: "https://winterfell.westeros.gov/events-from-stark-bank",
subscriptions: [
"boleto",
"boleto-payment",
"transfer",
"utility-payment"
]
)
webhook |> IO.inspect
using System;
StarkBank.Webhook webhook = StarkBank.Webhook.Create(
url: "https://winterfell.westeros.gov/events-from-stark-bank",
subscriptions: new List<string> { "transfer", "boleto", "boleto-payment", "utility-payment" }
);
package main
import (
"fmt"
"github.com/starkbank/sdk-go/starkbank/webhook"
)
func main() {
webhook, err := webhook.Create(
webhook.Webhook{
Url: "https://winterfell.westeros.gov/events-from-stark-bank",
Subscriptions: []string{"boleto", "boleto-payment", "transfer", "utility-payment"},
}, nil)
if err.Errors != nil {
for _, e := range err.Errors {
fmt.Printf("code: %s, message: %s", e.Code, e.Message)
}
}
fmt.Printf("%+v", webhook)
}
(def webhook
(starkbank.webhook/create
{
:url "https://winterfell.westeros.gov/events-from-stark-bank"
:subscriptions ["transfer" "boleto" "boleto-payment" "utility-payment"]
}))
(dorun (map println webhook))
curl --location --request POST '{{baseUrl}}/v2/webhook'
--header 'Access-Id: {{accessId}}'
--header 'Access-Time: {{accessTime}}'
--header 'Access-Signature: {{accessSignature}}'
--header 'Content-Type: application/json'
--data-raw '{
"url": "https://winterfell.westeros.gov/events-from-stark-bank",
"subscriptions": ["boleto", "boleto-payment", "transfer", "utility-payment"]
}'
Webhook(
id=6225875037061120,
subscriptions=['boleto', 'boleto-payment', 'transfer', 'utility-payment'],
url=https://winterfell.westeros.gov/events-from-stark-bank
)
Webhook {
id: '6225875037061120',
url: 'https://winterfell.westeros.gov/events-from-stark-bank',
subscriptions: [ 'transfer', 'boleto', 'boleto-payment', 'utility-payment' ]
}
StarkBank\Webhook Object
(
[id] => 6225875037061120
[url] => https://winterfell.westeros.gov/events-from-stark-bank
[subscriptions] => Array
(
[0] => boleto
[1] => boleto-payment
[2] => transfer
[3] => utility-payment
)
)
Webhook({
"id": "6225875037061120",
"url": "https://winterfell.westeros.gov/events-from-stark-bank",
"subscriptions": ["boleto", "boleto-payment", "transfer", "utility-payment"]
})
webhook( id: 6225875037061120, url: https://winterfell.westeros.gov/events-from-stark-bank, subscriptions: ["boleto", "boleto-payment", "transfer", "utility-payment"] )
%StarkBank.Webhook{
id: "6225875037061120",
url: "https://winterfell.westeros.gov/events-from-stark-bank",
subscriptions: [
"boleto",
"boleto-payment",
"transfer",
"utility-payment"
]
}
Webhook(
Url: https://winterfell.westeros.gov/events-from-stark-bank,
Subscriptions: { transfer, boleto, boleto-payment, utility-payment },
ID: 6225875037061120
)
{
Url:https://winterfell.westeros.gov/events-from-stark-bank
Subscriptions:[boleto boleto-payment transfer utility-payment]
Id:6225875037061120
}
{:id "6225875037061120",
:url "https://winterfell.westeros.gov/events-from-stark-bank",
:subscriptions
["boleto" "boleto-payment" "transfer" "utility-payment"]}
{
"message": "Webhook successfully created",
"webhook": {
"id": "6225875037061120",
"url": "https://winterfell.westeros.gov/events-from-stark-bank",
"subscriptions": [
"boleto",
"boleto-payment",
"transfer",
"utility-payment"
]
}
}
You can list all active webhook subscriptions to check your current configuration.
import starkbank
webhooks = starkbank.webhook.query()
for webhook in webhooks:
print(webhook)
const starkbank = require('starkbank');
(async() => {
let webhooks = await starkbank.webhook.query();
for await (let webhook of webhooks) {
console.log(webhook);
}
})();
$webhooks = StarkBank\Webhook::query();
foreach($webhooks as $webhook){
print_r($webhook);
}
import com.starkbank.*;
import com.starkbank.utils.Generator;
Generator<Webhook> webhooks = Webhook.query();
for (Webhook webhook : webhooks){
System.out.println(webhook);
}
require('starkbank')
webhooks = StarkBank::Webhook.query()
webhooks.each do |webhook|
puts webhook
end
webhooks = StarkBank.Webhook.query!()
for webhook <- webhooks do
webhook |> IO.inspect
end
using System;
using System.Collections.Generic;
IEnumerable<StarkBank.Webhook> webhooks = StarkBank.Webhook.Query();
foreach(StarkBank.Webhook webhook in webhooks)
{
Console.WriteLine(webhook);
}
package main
import (
"fmt"
"github.com/starkbank/sdk-go/starkbank/webhook"
)
func main() {
webhooks, errorChannel := webhook.Query(nil, nil)
loop:
for {
select {
case err := <-errorChannel:
if err.Errors != nil {
for _, e := range err.Errors {
fmt.Printf("code: %s, message: %s", e.Code, e.Message)
}
}
case webhook, ok := <-webhooks:
if !ok {
break loop
}
fmt.Printf("%+v", webhook)
}
}
}
(def webhooks (starkbank.webhook/query)) (dorun (map println webhooks))
curl --location --request GET '{{baseUrl}}/v2/webhook'
--header 'Access-Id: {{accessId}}'
--header 'Access-Time: {{accessTime}}'
--header 'Access-Signature: {{accessSignature}}'
Webhook(
id=6225875037061120,
subscriptions=['boleto', 'boleto-payment', 'transfer', 'utility-payment'],
url=https://winterfell.westeros.gov/events-from-stark-bank
)
Webhook {
url: 'https://winterfell.westeros.gov/events-from-stark-bank',
subscriptions: [ 'transfer', 'boleto', 'boleto-payment', 'utility-payment' ],
id: '6225875037061120'
}
StarkBank\Webhook Object
(
[id] => 6225875037061120
[url] => https://winterfell.westeros.gov/events-from-stark-bank
[subscriptions] => Array
(
[0] => boleto
[1] => boleto-payment
[2] => transfer
[3] => utility-payment
)
)
Webhook({
"id": "6225875037061120",
"url": "https://winterfell.westeros.gov/events-from-stark-bank",
"subscriptions": ["boleto", "boleto-payment", "transfer", "utility-payment"]
})
webhook(
id: 6225875037061120,
url: https://winterfell.westeros.gov/events-from-stark-bank,
subscriptions: ["boleto", "boleto-payment", "transfer", "utility-payment"]
)
%StarkBank.Webhook{
id: "4844331563220992",
url: "https://winterfell.westeros.gov/events-from-stark-bank",
subscriptions: [
"boleto",
"boleto-payment",
"transfer",
"utility-payment"
]
}
Webhook(
Url: https://webhook.site/60e9c18e-4b5c-4369-bda1-ab5fcd8e1b29,
Subscriptions: { transfer, boleto, boleto-payment, utility-payment },
ID: 6225875037061120
)
{
Url:https://winterfell.westeros.gov/events-from-stark-bank
Subscriptions:[boleto boleto-payment transfer utility-payment]
Id:6225875037061120
}
{:id "6225875037061120",
:url "https://winterfell.westeros.gov/events-from-stark-bank",
:subscriptions
["boleto" "boleto-payment" "transfer" "utility-payment"]}
{
"cursor": null,
"webhooks": [
{
"id": "6225875037061120",
"url": "https://winterfell.westeros.gov/events-from-stark-bank",
"subscriptions": [
"boleto",
"boleto-payment",
"transfer",
"utility-payment"
]
}
]
}
Delete a webhook subscription when you no longer want to receive events at that URL.
This action cannot be undone.
import starkbank
webhook = starkbank.webhook.delete("6225875037061120")
print(webhook)
const starkbank = require('starkbank');
(async() => {
let webhook = await starkbank.webhook.delete('6225875037061120');
console.log(webhook);
})();
$webhook = StarkBank\Webhook::delete("6225875037061120");
print_r($webhook);
import com.starkbank.*;
Webhook webhook = Webhook.delete("6225875037061120");
System.out.println(webhook);
require('starkbank')
webhook = StarkBank::Webhook.delete('6225875037061120')
puts webhook
webhook = StarkBank.Webhook.delete!("6225875037061120")
webhook |> IO.inspect
using System;
StarkBank.Webhook webhook = StarkBank.Webhook.Delete("6225875037061120");
Console.WriteLine(webhook);
package main
import (
"fmt"
"github.com/starkbank/sdk-go/starkbank/webhook"
)
func main() {
webhook, err := webhook.Delete("6225875037061120", nil)
if err.Errors != nil {
for _, e := range err.Errors {
fmt.Printf("code: %s, message: %s", e.Code, e.Message)
}
}
fmt.Printf("%+v", webhook)
}
(def webhook (starkbank.webhook/delete "6225875037061120")) (println webhook)
curl --location --request DELETE '{{baseUrl}}/v2/webhook/6225875037061120'
--header 'Access-Id: {{accessId}}'
--header 'Access-Time: {{accessTime}}'
--header 'Access-Signature: {{accessSignature}}'
Webhook(
id=6225875037061120,
subscriptions=['boleto', 'boleto-payment', 'transfer', 'utility-payment'],
url=https://winterfell.westeros.gov/events-from-stark-bank
)
Webhook {
id: '6225875037061120',
url: 'https://winterfell.westeros.gov/events-from-stark-bank',
subscriptions: [ 'boleto', 'boleto-payment', 'transfer', 'utility-payment' ]
}
StarkBank\Webhook Object
(
[id] => 6225875037061120
[url] => https://winterfell.westeros.gov/events-from-stark-bank
[subscriptions] => Array
(
[0] => boleto
[1] => boleto-payment
[2] => transfer
[3] => utility-payment
)
)
Webhook({
"id": "6225875037061120",
"url": "https://winterfell.westeros.gov/events-from-stark-bank",
"subscriptions": ["boleto", "boleto-payment", "transfer", "utility-payment"]
})
webhook( id: 6225875037061120, url: https://winterfell.westeros.gov/events-from-stark-bank, subscriptions: ["boleto", "boleto-payment", "transfer", "utility-payment"] )
%StarkBank.Webhook{
id: "6225875037061120",
url: "https://winterfell.westeros.gov/events-from-stark-bank",
subscriptions: [
"boleto",
"boleto-payment",
"transfer",
"utility-payment"
]
}
Webhook(
Url: https://webhook.site/60e9c18e-4b5c-4369-bda1-ab5fcd8e1b29,
Subscriptions: { transfer, boleto, boleto-payment, utility-payment },
ID: 6225875037061120
)
{
Url:https://winterfell.westeros.gov/events-from-stark-bank
Subscriptions:[boleto boleto-payment transfer utility-payment]
Id:6225875037061120
}
{:id "6225875037061120",
:url "https://winterfell.westeros.gov/events-from-stark-bank",
:subscriptions
["boleto" "boleto-payment" "transfer" "utility-payment"]}
{
"message": "Webhook successfully deleted",
"webhook": {
"id": "6225875037061120",
"url": "https://winterfell.westeros.gov/events-from-stark-bank",
"subscriptions": [
"boleto",
"boleto-payment",
"transfer",
"utility-payment"
]
}
}
Every time a log is created for a subscribed resource, Stark Bank generates an Event and delivers it to your webhook URL via a POST request.
Each event contains a subscription field indicating the resource type (e.g. transfer, invoice) and a log property with the details of what changed. The nature of the log depends on the subscription that triggered the event.
When Stark Bank sends an event to your webhook URL, it includes a Digital-Signature header. Use the SDK's event.parse() method to both parse the event and verify the signature automatically.
The SDK verifies the signature using Stark Bank's public key, ensuring the event was genuinely sent by Stark Bank. Never process events without verifying the signature.
import starkbank
request = listen() # this is the method you made to get the events posted to your Webhook endpoint
event = starkbank.event.parse(
content=request.data.decode("utf-8"),
signature=request.headers["Digital-Signature"],
)
if "transfer" in event.subscription:
print(event.log.request)
const starkbank = require('starkbank');
const express = require('express')
const app = express()
app.use(express.raw({type: "*/*"}));
const port = 3000
app.get('/', async (req, res) => {
try {
let event = await starkbank.event.parse({
content: req.body.toString(),
signature: req.headers['Digital-Signature']
});
if (event.subscription === 'transfer') {
console.log(event.log.request);
}
res.end()
}
catch (err) {
console.log(err)
res.status(400).end()
}
})
app.listen(port, () => console.log('Example app listening at http://localhost:{port}'))
use StarkBank\Event;
$response = listen() # this is the method you made to get the events posted to your Webhook
$event = Event::parse(
$response->content,
$response->headers["Digital-Signature"]
);
if ($event->subscription == "transfer"){
print_r($event->log->request);
import com.starkbank.*;
Request request = Listener.listen(); // this is the method you made to get the events posted to your Webhook
String content = request.content.toString();
String signature = request.headers.get("Digital-Signature");
Event event = Event.parse(content, signature);
if(event.subscription == "transfer"){) {
Transfer.Log log = ((Event.Transfer) event).log;
System.out.println(log.request);
}
require('starkbank')
request = listen() # this is the method you made to get the events posted to your Webhook
event = StarkBank::Event.parse(
content: request.body.read,
signature: request.headers['Digital-Signature']
)
if event.subscription == 'transfer'
puts event.log.request
end
response = listen() # this is the function you made to get the events posted to your Webhook
{event, cache_pid} = StarkBank.Event.parse!(
content: response.content,
signature: response.headers["Digital-Signature"]
) |> IO.inspect
using System;
Response response = listen(); // this is the method you made to get the events posted to your Webhook endpoint
StarkBank.Event parsedEvent = StarkBank.Event.Parse(
content: response.Content,
signature: response.Headers["Digital-Signature"]
);
if (parsedEvent.Subscription == "transfer") {
StarkBank.Transfer.Log log = transfer.Log as StarkBank.Transfer.Log;
Console.WriteLine(log.request);
}
Not yet available. Please contact us if you need this SDK.
Not yet available. Please contact us if you need this SDK.
Not yet available. Please contact us if you need this SDK.
{
"event": {
"created": "2024-02-01T02:06:27.872660+00:00",
"id": "5258020443389952",
"log": {
"created": "2024-02-01T02:06:26.317809+00:00",
"errors": [],
"id": "4638457385189376",
"transfer": {
"accountNumber": "123456-0",
"accountType": "checking",
"amount": 10000,
"bankCode": "001",
"branchCode": "1234",
"created": "2024-02-01T02:06:26.294998+00:00",
"description": "Payment for service #1234",
"externalId": "my_external_id",
"fee": 0,
"id": "6679150966341632",
"metadata": {},
"name": "Steve Rogers",
"rules": [
{
"key": "resendingLimit",
"value": 5
}
],
"scheduled": "2024-12-02T10:00:00+00:00",
"status": "success",
"tags": [
"debts",
"food"
],
"taxId": "330.731.970-10",
"transactionIds": [],
"updated": "2024-02-01T02:06:26.317865+00:00"
},
"type": "success"
},
"subscription": "transfer",
"workspaceId": "6341320293482496"
}
}
{
"event": {
"created": "2024-02-01T02:06:27.872660+00:00",
"id": "5258020443389952",
"log": {
"created": "2024-02-01T02:06:26.317809+00:00",
"errors": [],
"id": "4638457385189376",
"transfer": {
"accountNumber": "123456-0",
"accountType": "checking",
"amount": 10000,
"bankCode": "001",
"branchCode": "1234",
"created": "2024-02-01T02:06:26.294998+00:00",
"description": "Payment for service #1234",
"externalId": "my_external_id",
"fee": 0,
"id": "6679150966341632",
"metadata": {},
"name": "Steve Rogers",
"rules": [
{
"key": "resendingLimit",
"value": 5
}
],
"scheduled": "2024-12-02T10:00:00+00:00",
"status": "success",
"tags": [
"debts",
"food"
],
"taxId": "330.731.970-10",
"transactionIds": [],
"updated": "2024-02-01T02:06:26.317865+00:00"
},
"type": "success"
},
"subscription": "transfer",
"workspaceId": "6341320293482496"
}
}
{
"event": {
"created": "2024-02-01T02:06:27.872660+00:00",
"id": "5258020443389952",
"log": {
"created": "2024-02-01T02:06:26.317809+00:00",
"errors": [],
"id": "4638457385189376",
"transfer": {
"accountNumber": "123456-0",
"accountType": "checking",
"amount": 10000,
"bankCode": "001",
"branchCode": "1234",
"created": "2024-02-01T02:06:26.294998+00:00",
"description": "Payment for service #1234",
"externalId": "my_external_id",
"fee": 0,
"id": "6679150966341632",
"metadata": {},
"name": "Steve Rogers",
"rules": [
{
"key": "resendingLimit",
"value": 5
}
],
"scheduled": "2024-12-02T10:00:00+00:00",
"status": "success",
"tags": [
"debts",
"food"
],
"taxId": "330.731.970-10",
"transactionIds": [],
"updated": "2024-02-01T02:06:26.317865+00:00"
},
"type": "success"
},
"subscription": "transfer",
"workspaceId": "6341320293482496"
}
}
{
"event": {
"created": "2024-02-01T02:06:27.872660+00:00",
"id": "5258020443389952",
"log": {
"created": "2024-02-01T02:06:26.317809+00:00",
"errors": [],
"id": "4638457385189376",
"transfer": {
"accountNumber": "123456-0",
"accountType": "checking",
"amount": 10000,
"bankCode": "001",
"branchCode": "1234",
"created": "2024-02-01T02:06:26.294998+00:00",
"description": "Payment for service #1234",
"externalId": "my_external_id",
"fee": 0,
"id": "6679150966341632",
"metadata": {},
"name": "Steve Rogers",
"rules": [
{
"key": "resendingLimit",
"value": 5
}
],
"scheduled": "2024-12-02T10:00:00+00:00",
"status": "success",
"tags": [
"debts",
"food"
],
"taxId": "330.731.970-10",
"transactionIds": [],
"updated": "2024-02-01T02:06:26.317865+00:00"
},
"type": "success"
},
"subscription": "transfer",
"workspaceId": "6341320293482496"
}
}
{
"event": {
"created": "2024-02-01T02:06:27.872660+00:00",
"id": "5258020443389952",
"log": {
"created": "2024-02-01T02:06:26.317809+00:00",
"errors": [],
"id": "4638457385189376",
"transfer": {
"accountNumber": "123456-0",
"accountType": "checking",
"amount": 10000,
"bankCode": "001",
"branchCode": "1234",
"created": "2024-02-01T02:06:26.294998+00:00",
"description": "Payment for service #1234",
"externalId": "my_external_id",
"fee": 0,
"id": "6679150966341632",
"metadata": {},
"name": "Steve Rogers",
"rules": [
{
"key": "resendingLimit",
"value": 5
}
],
"scheduled": "2024-12-02T10:00:00+00:00",
"status": "success",
"tags": [
"debts",
"food"
],
"taxId": "330.731.970-10",
"transactionIds": [],
"updated": "2024-02-01T02:06:26.317865+00:00"
},
"type": "success"
},
"subscription": "transfer",
"workspaceId": "6341320293482496"
}
}
{
"event": {
"created": "2024-02-01T02:06:27.872660+00:00",
"id": "5258020443389952",
"log": {
"created": "2024-02-01T02:06:26.317809+00:00",
"errors": [],
"id": "4638457385189376",
"transfer": {
"accountNumber": "123456-0",
"accountType": "checking",
"amount": 10000,
"bankCode": "001",
"branchCode": "1234",
"created": "2024-02-01T02:06:26.294998+00:00",
"description": "Payment for service #1234",
"externalId": "my_external_id",
"fee": 0,
"id": "6679150966341632",
"metadata": {},
"name": "Steve Rogers",
"rules": [
{
"key": "resendingLimit",
"value": 5
}
],
"scheduled": "2024-12-02T10:00:00+00:00",
"status": "success",
"tags": [
"debts",
"food"
],
"taxId": "330.731.970-10",
"transactionIds": [],
"updated": "2024-02-01T02:06:26.317865+00:00"
},
"type": "success"
},
"subscription": "transfer",
"workspaceId": "6341320293482496"
}
}
{
"event": {
"created": "2024-02-01T02:06:27.872660+00:00",
"id": "5258020443389952",
"log": {
"created": "2024-02-01T02:06:26.317809+00:00",
"errors": [],
"id": "4638457385189376",
"transfer": {
"accountNumber": "123456-0",
"accountType": "checking",
"amount": 10000,
"bankCode": "001",
"branchCode": "1234",
"created": "2024-02-01T02:06:26.294998+00:00",
"description": "Payment for service #1234",
"externalId": "my_external_id",
"fee": 0,
"id": "6679150966341632",
"metadata": {},
"name": "Steve Rogers",
"rules": [
{
"key": "resendingLimit",
"value": 5
}
],
"scheduled": "2024-12-02T10:00:00+00:00",
"status": "success",
"tags": [
"debts",
"food"
],
"taxId": "330.731.970-10",
"transactionIds": [],
"updated": "2024-02-01T02:06:26.317865+00:00"
},
"type": "success"
},
"subscription": "transfer",
"workspaceId": "6341320293482496"
}
}
{
"event": {
"created": "2024-02-01T02:06:27.872660+00:00",
"id": "5258020443389952",
"log": {
"created": "2024-02-01T02:06:26.317809+00:00",
"errors": [],
"id": "4638457385189376",
"transfer": {
"accountNumber": "123456-0",
"accountType": "checking",
"amount": 10000,
"bankCode": "001",
"branchCode": "1234",
"created": "2024-02-01T02:06:26.294998+00:00",
"description": "Payment for service #1234",
"externalId": "my_external_id",
"fee": 0,
"id": "6679150966341632",
"metadata": {},
"name": "Steve Rogers",
"rules": [
{
"key": "resendingLimit",
"value": 5
}
],
"scheduled": "2024-12-02T10:00:00+00:00",
"status": "success",
"tags": [
"debts",
"food"
],
"taxId": "330.731.970-10",
"transactionIds": [],
"updated": "2024-02-01T02:06:26.317865+00:00"
},
"type": "success"
},
"subscription": "transfer",
"workspaceId": "6341320293482496"
}
}
{
"event": {
"created": "2024-02-01T02:06:27.872660+00:00",
"id": "5258020443389952",
"log": {
"created": "2024-02-01T02:06:26.317809+00:00",
"errors": [],
"id": "4638457385189376",
"transfer": {
"accountNumber": "123456-0",
"accountType": "checking",
"amount": 10000,
"bankCode": "001",
"branchCode": "1234",
"created": "2024-02-01T02:06:26.294998+00:00",
"description": "Payment for service #1234",
"externalId": "my_external_id",
"fee": 0,
"id": "6679150966341632",
"metadata": {},
"name": "Steve Rogers",
"rules": [
{
"key": "resendingLimit",
"value": 5
}
],
"scheduled": "2024-12-02T10:00:00+00:00",
"status": "success",
"tags": [
"debts",
"food"
],
"taxId": "330.731.970-10",
"transactionIds": [],
"updated": "2024-02-01T02:06:26.317865+00:00"
},
"type": "success"
},
"subscription": "transfer",
"workspaceId": "6341320293482496"
}
}
{
"event": {
"created": "2024-02-01T02:06:27.872660+00:00",
"id": "5258020443389952",
"log": {
"created": "2024-02-01T02:06:26.317809+00:00",
"errors": [],
"id": "4638457385189376",
"transfer": {
"accountNumber": "123456-0",
"accountType": "checking",
"amount": 10000,
"bankCode": "001",
"branchCode": "1234",
"created": "2024-02-01T02:06:26.294998+00:00",
"description": "Payment for service #1234",
"externalId": "my_external_id",
"fee": 0,
"id": "6679150966341632",
"metadata": {},
"name": "Steve Rogers",
"rules": [
{
"key": "resendingLimit",
"value": 5
}
],
"scheduled": "2024-12-02T10:00:00+00:00",
"status": "success",
"tags": [
"debts",
"food"
],
"taxId": "330.731.970-10",
"transactionIds": [],
"updated": "2024-02-01T02:06:26.317865+00:00"
},
"type": "success"
},
"subscription": "transfer",
"workspaceId": "6341320293482496"
}
}
You can get a specific event by its ID to inspect its details.
import starkbank
event = starkbank.event.get("4537025176797184")
print(event)
const starkbank = require('starkbank');
(async() => {
let event = await starkbank.event.get('4537025176797184');
console.log(event);
})();
$event = StarkBank\Event::get("4537025176797184");
print_r($event);
import com.starkbank.*;
Event event = Event.get("4537025176797184");
System.out.println(event);
require('starkbank')
event = StarkBank::Event.get('4537025176797184')
puts event
event = StarkBank.Event.get!("4537025176797184")
event |> IO.inspect
using System;
StarkBank.Event eventObject = StarkBank.Event.Get("4537025176797184");
Console.WriteLine(eventObject);
package main
import (
"fmt"
"github.com/starkbank/sdk-go/starkbank/event"
)
func main() {
event, err := event.Get("4537025176797184", nil)
if err.Errors != nil {
for _, e := range err.Errors {
fmt.Printf("code: %s, message: %s", e.Code, e.Message)
}
}
fmt.Printf("%+v", event)
}
(def event (starkbank.event/get "4537025176797184")) (println event)
curl --location --request GET '{{baseUrl}}/v2/event/4537025176797184'
--header 'Access-Id: {{accessId}}'
--header 'Access-Time: {{accessTime}}'
--header 'Access-Signature: {{accessSignature}}'
Event(
id=4537025176797184,
is_delivered=False,
subscription=transfer,
created=2020-04-24 17:49:10.181589,
log=Log(
id=5662318377566208,
created=2020-04-24 17:49:09.348444,
errors=[],
type=sending,
transfer=Transfer(
id=5950134772826112,
account_number=76543-8,
amount=100000000,
bank_code=665,
branch_code=2201,
created=2020-04-24 17:49:08.748893,
fee=200,
name=Daenerys Targaryen Stormborn,
status=processing,
tags=['daenerys', 'invoice/1234'],
tax_id=594.739.480-42,
transaction_ids=['5991715760504832'],
updated=2020-04-24 17:49:09.632271
)
),
workspace_id=1231231231231231
)
Event {
id: '4537025176797184',
created: '2020-04-24T17:49:10.847726+00:00',
isDelivered: false,
subscription: 'transfer',
log: {
id: '5662318377566208',
errors: [],
type: 'sending',
created: '2020-04-24T17:49:09.884128+00:00',
payment: {
id: '5950134772826112'
accountNumber: '76543-8',
amount: 10785,
bankCode: '665',
branchCode: '2201',
created: '2020-04-24T17:49:08.038706+00:00',
fee: 200,
name: 'Daenerys Targaryen Stormborn',
status: 'processing',
tags: ['daenerys', 'invoice/1234'],
taxId: '594.739.480-42',
transactionIds: ['5991715760504832'],
updated: '2020-04-24T17:49:09.038706+00:00',
}
},
workspaceId='1231231231231231'
}
StarkBank\Event Object
(
[id] => 4537025176797184
[isDelivered] => false
[subscription] => transfer
[created] => DateTime Object
(
[date] => 2020-04-24 17:49:10.616917
[timezone_type] => 1
[timezone] => +00:00
)
[log] => StarkBank\Transfer\Log Object
(
[id] => 5662318377566208
[created] => DateTime Object
(
[date] => 2020-04-24 17:49:09.844960
[timezone_type] => 1
[timezone] => +00:00
)
[type] => sending
[errors] => Array
(
)
[transfer] => StarkBankTransfer Object
(
[id] => 5950134772826112
[amount] => 100000000
[name] => Daenerys Targaryen Stormborn
[taxId] => 594.739.480-42
[bankCode] => 665
[branchCode] => 2201
[accountNumber] => 76543-8
[tags] => Array
(
[0] => daenerys
[1] => invoice/1234
)
[fee] => 200
[status] => processing
[transactionIds] => Array
(
[0] => 5991715760504832
)
[created] => DateTime Object
(
[date] => 2020-04-24 17:49:08.277606
[timezone_type] => 1
[timezone] => +00:00
)
[updated] => DateTime Object
(
[date] => 2020-04-24 17:49:09.090932
[timezone_type] => 1
[timezone] => +00:00
)
)
)
[workspaceId] => 1231231231231231
)
Event({
"id": "4537025176797184",
"created": "2020-04-24T17:49:10+00:00",
"isDelivered": false,
"subscription": "transfer",
"log": {
"id": "5662318377566208",
"created": "2020-04-24T17:49:13+00:00",
"type": "registered",
"errors": [],
"transfer": {
"id": "5429309233692672",
"accountNumber": "76543-8",
"amount": 100000000,
"bankCode": "665",
"branchCode": "2201",
"created": "2020-04-24T17:49:13+00:00"
"fee": 200,
"name": "Daenerys Targaryen Stormborn",
"status": "processing",
"tags": ["daenerys", "invoice/1234"],
"taxId": "594.739.480-42",
"transactionIds": ["5991715760504832"],
"updated": "2020-04-24T17:49:13+00:00"
}
},
"workspaceId": 1231231231231231
})
event(
id: 4537025176797184,
created: 2020-04-24T17:49:10+00:00,
is_delivered: false,
subscription: transfer,
log: log(
id: 5662318377566208,
created: 2020-04-24T17:49:09+00:00,
type: sending,
errors: [],
transfer: transfer(
id: 5950134772826112,
account_number: 76543-8,
amount: 100000000,
bank_code: 665,
branch_code: 2201,
created: 2020-04-24T17:49:09+00:00
fee: 200,
name: Daenerys Targaryen Stormborn,
status: processing,
tags: ["daenerys", "invoice/1234"],
tax_id: 594.739.480-42,
transaction_ids: ["5991715760504832"],
updated: 2020-04-24T17:49:09+00:00
)
),
workspace_id: 1231231231231231
)
%StarkBank.Event{
id: "4537025176797184",
is_delivered: false,
subscription: "transfer",
created: ~U[2020-04-24 17:49:09.594656Z],
log: %StarkBank.Transfer.Log{
id: "5662318377566208",
created: ~U[2020-04-24 17:49:09.049096Z],
errors: [],
type: "sending",
payment: %StarkBank.Transfer{
id: "5950134772826112",
account_number: 76543-8,
amount: 11631,
bank_code: "665",
branch_code: "2201",
created: ~U[2020-04-24 17:49:09.713657Z],
fee: 200,
name: "Daenerys Targaryen Stormborn",
status: "processing",
tags: ["daenerys", "invoice/1234"],
tax_id: "594.739.480-42"
transaction_ids: ["5991715760504832"],
updated: ~U[2020-04-24 17:49:09.713657Z]
}
},
workspace_id: "1231231231231231"
}
Event(
ID: 4537025176797184,
IsDelivered: False,
Subscription: transfer,
Created: 04/24/2020 17:49:09,
Log: Log(
ID: 5662318377566208,
Created: 04/24/2020 17:49:09,
Type: sending,
Errors: { },
Transfer: Transfer(
ID: 5950134772826112
AccountNumber: 76543-8,
Amount: 100000000,
BankCode: 665,
BranchCode: 2201,
Created: 04/24/2020 17:49:09,
Fee: 200,
Name: Daenerys Targaryen Stormborn,
Status: processing,
Tags: { daenerys, invoice/1234 },
TaxID: 594.739.480-42,
TransactionIds: { 5991715760504832 },
Updated: 04/24/2020 17:49:09
)
),
WorkspaceId: 1231231231231231
)
{
Id:4537025176797184
Log:{
Id:5662318377566208
Transfer:{
Id:5950134772826112
AccountNumber:76543-8
Amount:1000000
BankCode:665
BranchCode:2201
Created:2020-04-24 17:49:10.38386 +0000 +0000
Fine:200
Name:Daenerys Targaryen Stormborn
Status:processing
Tags:[daenerys invoice/1234]
TaxId:594.739.480-42
TransactionIds:[5991715760504832]
Created:2020-04-24 17:49:09.38386 +0000 +0000
}
Errors:[]
Type:sending
Created:2020-04-24 17:49:09.126413 +0000 +0000
}
Created:2020-04-24 17:49:09.464471 +0000 +0000
IsDelivered:false
Subscription:transfer
WorkspaceId:1231231231231231
}
{:id "4537025176797184",
:created "2020-04-24T17:49:09.359338+00:00",
:is-delivered false,
:subscription "transfer",
:log
{:id "5662318377566208",
:created "2020-04-24T17:49:09.703951+00:00",
:errors [],
:type "sending",
:transfer
{:id "5950134772826112",
:account-number 76543-8,
:amount 100000000,
:bank-code "665",
:branch-code "2201",
:created "2020-04-24T17:49:09.128124+00:00",
:fee 200,
:name "Daenerys Targaryen Stormborn",
:status "processing",
:tags ["daenerys" "invoice/1234"],
:transaction-ids ["5991715760504832"],
:updated "2020-04-24T17:49:09.128124+00:00"}}
:workspace-id "1231231231231231"}
{
"message": "Event successfully deleted",
"event": {
"id": "4537025176797184",
"isDelivered": false,
"subscription": "transfer",
"created": "2020-04-24T17:49:00.201602+00:00",
"log": {
"id": "5662318377566208",
"errors": [],
"type": "sending",
"created": "2020-04-24T17:49:09.751122+00:00",
"transfer": {
"id": "5950134772826112",
"accountNumber": "76543-8",
"amount": 100000000,
"bankCode": "665",
"branchCode": "2201",
"created": "2020-04-24T17:49:09.130246+00:00",
"fee": 200,
"name": "Daenerys Targaryen Stormborn",
"status": "processing",
"taxId": "594.739.480-42",
"tags": ["daenerys", "invoice/1234"],
"transactionIds": ["5991715760504832"],
"updated": "2020-04-24T17:49:02.130255+00:00",
}
},
"workspaceId": "1231231231231231"
}
}
You can list all events that match your filters. Use the isDelivered parameter to filter events that haven't been successfully delivered.
This is especially useful for building a resilience mechanism: periodically query for undelivered events, process them, and mark them as delivered.
import starkbank
events = starkbank.event.query(
is_delivered=False,
after="2020-04-01",
before="2020-04-30"
)
for event in events:
print(event)
const starkbank = require('starkbank');
(async() => {
let events = await starkbank.event.query({
isDelivered: false,
after: '2020-04-01',
before: '2020-04-30',
});
for await (let event of events) {
console.log(event);
}
})();
$events = StarkBank\Event::query([
"isDelivered" => false,
"after" => "2020-04-01",
"before" => "2020-04-30"
]);
foreach($events as $event){
print_r($event);
}
import com.starkbank.*;
import com.starkbank.utils.Generator;
import java.util.HashMap;
HashMap<String, Object> params = new HashMap<>();
params.put("isDelivered", false);
params.put("after", "2020-04-01");
params.put("before", "2020-04-30");
Generator<Event> events = Event.query(params);
for (Event event : events){
System.out.println(event);
}
require('starkbank')
events = StarkBank::Event.query(
after: '2020-04-01',
before: '2020-04-30',
is_delivered: false
)
events.each do |event|
puts event
end
events = StarkBank.Event.query!(
after: "2020-04-01",
before: "2020-04-30",
is_delivered: false
)
for event <- events do
event |> IO.inspect
end
using System;
using System.Collections.Generic;
IEnumerable<StarkBank.Event> events = StarkBank.Event.Query(
after: new DateTime(2020, 4, 1),
before: new DateTime(2020, 4, 30),
isDelivered: false
);
foreach(StarkBank.Event eventObject in events)
{
Console.WriteLine(eventObject);
}
package main
import (
"fmt"
"time"
"github.com/starkbank/sdk-go/starkbank/event"
)
func main() {
var params = map[string]interface{}{}
params["isDelivered"] = false
params["after"] = time.Date(2020, 4, 1, 0, 0, 0, 0, time.UTC)
params["before"] = time.Date(2020, 4, 30, 0, 0, 0, 0, time.UTC)
events, errorChannel := event.Query(params, nil)
loop:
for {
select {
case err := <-errorChannel:
if err.Errors != nil {
for _, e := range err.Errors {
fmt.Printf("code: %s, message: %s", e.Code, e.Message)
}
}
case event, ok := <-events:
if !ok {
break loop
}
fmt.Printf("%+v", event)
}
}
}
(def events
(starkbank.event/query
{
:after "2020-03-20"
:before "2020-04-30"
:is-delivered false
}))
(dorun (map println events))
curl --location --request GET '{{baseUrl}}/v2/event'
--header 'Access-Id: {{accessId}}'
--header 'Access-Time: {{accessTime}}'
--header 'Access-Signature: {{accessSignature}}'
Event(
id=4537025176797184,
is_delivered=False,
subscription=transfer,
created=2020-04-24 17:49:10.181589,
log=Log(
id=5662318377566208,
created=2020-04-24 17:49:09.348444,
errors=[],
type=sending,
transfer=Transfer(
id=5950134772826112,
account_number=76543-8,
amount=100000000,
bank_code=665,
branch_code=2201,
created=2020-04-24 17:49:08.748893,
fee=200,
name=Daenerys Targaryen Stormborn,
status=processing,
tags=['daenerys', 'invoice/1234'],
tax_id=594.739.480-42,
transaction_ids=['5991715760504832'],
updated=2020-04-24 17:49:09.632271
)
),
workspace_id=1231231231231231
)
Event {
id: '4537025176797184',
created: '2020-04-24T17:49:10.847726+00:00',
isDelivered: false,
subscription: 'transfer',
log: {
id: '5662318377566208',
errors: [],
type: 'sending',
created: '2020-04-24T17:49:09.884128+00:00',
payment: {
id: '5950134772826112'
accountNumber: '76543-8',
amount: 10785,
bankCode: '665',
branchCode: '2201',
created: '2020-04-24T17:49:08.038706+00:00',
fee: 200,
name: 'Daenerys Targaryen Stormborn',
status: 'processing',
tags: ['daenerys', 'invoice/1234'],
taxId: '594.739.480-42',
transactionIds: ['5991715760504832'],
updated: '2020-04-24T17:49:09.038706+00:00',
}
},
workspaceId='1231231231231231'
}
StarkBank\Event Object
(
[id] => 4537025176797184
[isDelivered] => false
[subscription] => transfer
[created] => DateTime Object
(
[date] => 2020-04-24 17:49:10.616917
[timezone_type] => 1
[timezone] => +00:00
)
[log] => StarkBank\Transfer\Log Object
(
[id] => 5662318377566208
[created] => DateTime Object
(
[date] => 2020-04-24 17:49:09.844960
[timezone_type] => 1
[timezone] => +00:00
)
[type] => sending
[errors] => Array
(
)
[transfer] => StarkBank\Transfer Object
(
[id] => 5950134772826112
[amount] => 100000000
[name] => Daenerys Targaryen Stormborn
[taxId] => 594.739.480-42
[bankCode] => 665
[branchCode] => 2201
[accountNumber] => 76543-8
[tags] => Array
(
[0] => daenerys
[1] => invoice/1234
)
[fee] => 200
[status] => processing
[transactionIds] => Array
(
[0] => 5991715760504832
)
[created] => DateTime Object
(
[date] => 2020-04-24 17:49:08.277606
[timezone_type] => 1
[timezone] => +00:00
)
[updated] => DateTime Object
(
[date] => 2020-04-24 17:49:09.090932
[timezone_type] => 1
[timezone] => +00:00
)
)
)
[workspaceId] => 1231231231231231
)
Event({
"id": "4537025176797184",
"created": "2020-04-24T17:49:10+00:00",
"isDelivered": false,
"subscription": "transfer",
"log": {
"id": "5662318377566208",
"created": "2020-04-24T17:49:13+00:00",
"type": "registered",
"errors": [],
"transfer": {
"id": "5429309233692672",
"accountNumber": "76543-8",
"amount": 100000000,
"bankCode": "665",
"branchCode": "2201",
"created": "2020-04-24T17:49:13+00:00"
"fee": 200,
"name": "Daenerys Targaryen Stormborn",
"status": "processing",
"tags": ["daenerys", "invoice/1234"],
"taxId": "594.739.480-42",
"transactionIds": ["5991715760504832"],
"updated": "2020-04-24T17:49:13+00:00"
}
},
"workspaceId": 1231231231231231
})
event(
id: 4537025176797184,
created: 2020-04-24T17:49:10+00:00,
is_delivered: false,
subscription: transfer,
log: log(
id: 5662318377566208,
created: 2020-04-24T17:49:09+00:00,
type: sending,
errors: [],
transfer: transfer(
id: 5950134772826112,
account_number: 76543-8,
amount: 100000000,
bank_code: 665,
branch_code: 2201,
created: 2020-04-24T17:49:09+00:00
fee: 200,
name: Daenerys Targaryen Stormborn,
status: processing,
tags: ["daenerys", "invoice/1234"],
tax_id: 594.739.480-42,
transaction_ids: ["5991715760504832"],
updated: 2020-04-24T17:49:09+00:00
)
),
workspace_id: 1231231231231231
)
%StarkBank.Event{
id: "4537025176797184",
is_delivered: false,
subscription: "transfer",
created: ~U[2020-04-24 17:49:09.594656Z],
log: %StarkBank.Transfer.Log{
id: "5662318377566208",
created: ~U[2020-04-24 17:49:09.049096Z],
errors: [],
type: "sending",
payment: %StarkBank.Transfer{
id: "5950134772826112",
account_number: 76543-8,
amount: 11631,
bank_code: "665",
branch_code: "2201",
created: ~U[2020-04-24 17:49:09.713657Z],
fee: 200,
name: "Daenerys Targaryen Stormborn",
status: "processing",
tags: ["daenerys", "invoice/1234"],
tax_id: "594.739.480-42"
transaction_ids: ["5991715760504832"],
updated: ~U[2020-04-24 17:49:09.713657Z]
}
},
workspace_id: "1231231231231231"
}
Event(
ID: 4537025176797184,
IsDelivered: False,
Subscription: transfer,
Created: 04/24/2020 17:49:09,
Log: Log(
ID: 5662318377566208,
Created: 04/24/2020 17:49:09,
Type: sending,
Errors: { },
Transfer: Transfer(
ID: 5950134772826112
AccountNumber: 76543-8,
Amount: 100000000,
BankCode: 665,
BranchCode: 2201,
Created: 04/24/2020 17:49:09,
Fee: 200,
Name: Daenerys Targaryen Stormborn,
Status: processing,
Tags: { daenerys, invoice/1234 },
TaxID: 594.739.480-42,
TransactionIds: { 5991715760504832 },
Updated: 04/24/2020 17:49:09
)
),
WorkspaceId: 1231231231231231
)
{
Id:4537025176797184
Log:{
Id:5662318377566208
Transfer:{
Id:5950134772826112
AccountNumber:76543-8
Amount:1000000
BankCode:665
BranchCode:2201
Created:2020-04-24 17:49:10.38386 +0000 +0000
Fine:200
Name:Daenerys Targaryen Stormborn
Status:processing
Tags:[daenerys invoice/1234]
TaxId:594.739.480-42
TransactionIds:[5991715760504832]
Created:2020-04-24 17:49:09.38386 +0000 +0000
}
Errors:[]
Type:sending
Created:2020-04-24 17:49:09.126413 +0000 +0000
}
Created:2020-04-24 17:49:09.464471 +0000 +0000
IsDelivered:false
Subscription:transfer
WorkspaceId:1231231231231231
}
{:id "4537025176797184",
:created "2020-04-24T17:49:09.359338+00:00",
:is-delivered false,
:subscription "transfer",
:log
{:id "5662318377566208",
:created "2020-04-24T17:49:09.703951+00:00",
:errors [],
:type "sending",
:transfer
{:id "5950134772826112",
:account-number 76543-8,
:amount 100000000,
:bank-code "665",
:branch-code "2201",
:created "2020-04-24T17:49:09.128124+00:00",
:fee 200,
:name "Daenerys Targaryen Stormborn",
:status "processing",
:tags ["daenerys" "invoice/1234"],
:transaction-ids ["5991715760504832"],
:updated "2020-04-24T17:49:09.128124+00:00"}}
:workspace-id "1231231231231231"}
{
"cursor": null,
"events": [
{
"id": "4537025176797184",
"isDelivered": false,
"subscription": "transfer",
"created": "2020-04-24T17:49:00.201602+00:00",
"log": {
"id": "5662318377566208",
"errors": [],
"type": "sending",
"created": "2020-04-24T17:49:09.751122+00:00",
"transfer": {
"id": "5950134772826112",
"accountNumber": "76543-8",
"amount": 100000000,
"bankCode": "665",
"branchCode": "2201",
"created": "2020-04-24T17:49:09.130246+00:00",
"fee": 200,
"name": "Daenerys Targaryen Stormborn",
"status": "processing",
"taxId": "594.739.480-42",
"tags": ["daenerys", "invoice/1234"],
"transactionIds": ["5991715760504832"],
"updated": "2020-04-24T17:49:02.130255+00:00",
}
},
"workspaceId": "1231231231231231"
}
]
}
After processing an event, you can mark it as delivered by updating the isDelivered property to true.
This is particularly useful after recovering from server downtime: list all undelivered events, process them, and then set them as delivered.
import starkbank
event = starkbank.event.update(
"4537025176797184",
is_delivered=True
)
print(event)
const starkbank = require('starkbank');
(async() => {
let event = await starkbank.event.update(
'4537025176797184',
{isDelivered: true}
);
console.log(event);
})();
$event = StarkBank\Event::update(
"4537025176797184",
["isDelivered" => true]
);
print_r($event);
import com.starkbank.*;
import java.util.HashMap;
HashMap<String, Object> params = new HashMap<>();
params.put("isDelivered", true);
Event event = Event.update(
"4537025176797184",
params
);
System.out.println(event);
require('starkbank')
event = StarkBank::Event.update(
'4537025176797184',
is_delivered: true
)
puts event
event = StarkBank.Event.update!(
"4537025176797184",
is_delivered: true
)
event |> IO.inspect
using System;
StarkBank.Event eventObject = StarkBank.Event.Update(
"4537025176797184",
isDelivered: true
);
Console.WriteLine(eventObject);
package main
import (
"fmt"
"github.com/starkbank/sdk-go/starkbank/event"
)
func main() {
patchData := map[string]interface{}{}
patchData["isDelivered"] = true
event, err := event.Update(
"4537025176797184",
patchData,
nil,
)
if err.Errors != nil {
for _, e := range err.Errors {
fmt.Printf("code: %s, message: %s", e.Code, e.Message)
}
}
fmt.Printf("%+v", event)
}
(def event
(starkbank.event/update
"4537025176797184"
{:is-delivered true}))
(println event)
curl --location --request PATCH '{{baseUrl}}/v2/event/4537025176797184'
--header 'Access-Id: {{accessId}}'
--header 'Access-Time: {{accessTime}}'
--header 'Access-Signature: {{accessSignature}}'
--header 'Content-Type: application/json'
--data-raw '{
"isDelivered": true
}'
Event(
id=4537025176797184,
is_delivered=True,
subscription=transfer,
created=2020-04-24 17:49:10.181589,
log=Log(
id=5662318377566208,
created=2020-04-24 17:49:09.348444,
errors=[],
type=sending,
transfer=Transfer(
id=5950134772826112,
account_number=76543-8,
amount=100000000,
bank_code=665,
branch_code=2201,
created=2020-04-24 17:49:08.748893,
fee=200,
name=Daenerys Targaryen Stormborn,
status=processing,
tags=['daenerys', 'invoice/1234'],
tax_id=594.739.480-42,
transaction_ids=['5991715760504832'],
updated=2020-04-24 17:49:09.632271
)
),
workspace_id=1231231231231231
)
Event {
id: '4537025176797184',
created: '2020-04-24T17:49:10.847726+00:00',
isDelivered: true,
subscription: 'transfer',
log: {
id: '5662318377566208',
errors: [],
type: 'sending',
created: '2020-04-24T17:49:09.884128+00:00',
payment: {
id: '5950134772826112'
accountNumber: '76543-8',
amount: 10785,
bankCode: '665',
branchCode: '2201',
created: '2020-04-24T17:49:08.038706+00:00',
fee: 200,
name: 'Daenerys Targaryen Stormborn',
status: 'processing',
tags: ['daenerys', 'invoice/1234'],
taxId: '594.739.480-42',
transactionIds: ['5991715760504832'],
updated: '2020-04-24T17:49:09.038706+00:00',
}
},
workspaceId='1231231231231231'
}
StarkBank\Event Object
(
[id] => 4537025176797184
[isDelivered] => true
[subscription] => transfer
[created] => DateTime Object
(
[date] => 2020-04-24 17:49:10.616917
[timezone_type] => 1
[timezone] => +00:00
)
[log] => StarkBankTransferLog Object
(
[id] => 5662318377566208
[created] => DateTime Object
(
[date] => 2020-04-24 17:49:09.844960
[timezone_type] => 1
[timezone] => +00:00
)
[type] => sending
[errors] => Array
(
)
[transfer] => StarkBankTransfer Object
(
[id] => 5950134772826112
[amount] => 100000000
[name] => Daenerys Targaryen Stormborn
[taxId] => 594.739.480-42
[bankCode] => 665
[branchCode] => 2201
[accountNumber] => 76543-8
[tags] => Array
(
[0] => daenerys
[1] => invoice/1234
)
[fee] => 200
[status] => processing
[transactionIds] => Array
(
[0] => 5991715760504832
)
[created] => DateTime Object
(
[date] => 2020-04-24 17:49:08.277606
[timezone_type] => 1
[timezone] => +00:00
)
[updated] => DateTime Object
(
[date] => 2020-04-24 17:49:09.090932
[timezone_type] => 1
[timezone] => +00:00
)
)
)
[workspaceId] => 1231231231231231
)
Event({
"id": "4537025176797184",
"created": "2020-04-24T17:49:10+00:00",
"isDelivered": true,
"subscription": "transfer",
"log": {
"id": "5662318377566208",
"created": "2020-04-24T17:49:13+00:00",
"type": "registered",
"errors": [],
"transfer": {
"id": "5429309233692672",
"accountNumber": "76543-8",
"amount": 100000000,
"bankCode": "665",
"branchCode": "2201",
"created": "2020-04-24T17:49:13+00:00"
"fee": 200,
"name": "Daenerys Targaryen Stormborn",
"status": "processing",
"tags": ["daenerys", "invoice/1234"],
"taxId": "594.739.480-42",
"transactionIds": ["5991715760504832"],
"updated": "2020-04-24T17:49:13+00:00"
}
},
"workspaceId": 1231231231231231
})
event(
id: 4537025176797184,
created: 2020-04-24T17:49:10+00:00,
is_delivered: true,
subscription: transfer,
log: log(
id: 5662318377566208,
created: 2020-04-24T17:49:09+00:00,
type: sending,
errors: [],
transfer: transfer(
id: 5950134772826112,
account_number: 76543-8,
amount: 100000000,
bank_code: 665,
branch_code: 2201,
created: 2020-04-24T17:49:09+00:00
fee: 200,
name: Daenerys Targaryen Stormborn,
status: processing,
tags: ["daenerys", "invoice/1234"],
tax_id: 594.739.480-42,
transaction_ids: ["5991715760504832"],
updated: 2020-04-24T17:49:09+00:00
)
),
workspace_id: 1231231231231231
)
%StarkBank.Event{
id: "4537025176797184",
is_delivered: true,
subscription: "transfer",
created: ~U[2020-04-24 17:49:09.594656Z],
log: %StarkBank.Transfer.Log{
id: "5662318377566208",
created: ~U[2020-04-24 17:49:09.049096Z],
errors: [],
type: "sending",
payment: %StarkBank.Transfer{
id: "5950134772826112",
account_number: 76543-8,
amount: 11631,
bank_code: "665",
branch_code: "2201",
created: ~U[2020-04-24 17:49:09.713657Z],
fee: 200,
name: "Daenerys Targaryen Stormborn",
status: "processing",
tags: ["daenerys", "invoice/1234"],
tax_id: "594.739.480-42"
transaction_ids: ["5991715760504832"],
updated: ~U[2020-04-24 17:49:09.713657Z]
}
},
workspace_id: "1231231231231231"
}
Event(
ID: 4537025176797184,
IsDelivered: true,
Subscription: transfer,
Created: 04/24/2020 17:49:09,
Log: Log(
ID: 5662318377566208,
Created: 04/24/2020 17:49:09,
Type: sending,
Errors: { },
Transfer: Transfer(
ID: 5950134772826112
AccountNumber: 76543-8,
Amount: 100000000,
BankCode: 665,
BranchCode: 2201,
Created: 04/24/2020 17:49:09,
Fee: 200,
Name: Daenerys Targaryen Stormborn,
Status: processing,
Tags: { daenerys, invoice/1234 },
TaxID: 594.739.480-42,
TransactionIds: { 5991715760504832 },
Updated: 04/24/2020 17:49:09
)
),
WorkspaceId: 1231231231231231
)
{
Id:4537025176797184
Log:{
Id:5662318377566208
Transfer:{
Id:5950134772826112
AccountNumber:76543-8
Amount:1000000
BankCode:665
BranchCode:2201
Created:2020-04-24 17:49:10.38386 +0000 +0000
Fine:200
Name:Daenerys Targaryen Stormborn
Status:processing
Tags:[daenerys invoice/1234]
TaxId:594.739.480-42
TransactionIds:[5991715760504832]
Created:2020-04-24 17:49:09.38386 +0000 +0000
}
Errors:[]
Type:sending
Created:2020-04-24 17:49:09.126413 +0000 +0000
}
Created:2020-04-24 17:49:09.464471 +0000 +0000
IsDelivered:true
Subscription:transfer
WorkspaceId:1231231231231231
}
{:id "4537025176797184",
:created "2020-04-24T17:49:09.359338+00:00",
:is-delivered true,
:subscription "transfer",
:log
{:id "5662318377566208",
:created "2020-04-24T17:49:09.703951+00:00",
:errors [],
:type "sending",
:transfer
{:id "5950134772826112",
:account-number 76543-8,
:amount 100000000,
:bank-code "665",
:branch-code "2201",
:created "2020-04-24T17:49:09.128124+00:00",
:fee 200,
:name "Daenerys Targaryen Stormborn",
:status "processing",
:tags ["daenerys" "invoice/1234"],
:transaction-ids ["5991715760504832"],
:updated "2020-04-24T17:49:09.128124+00:00"}}
:workspace-id "1231231231231231"}
{
"message": "Event successfully patched",
"event": {
"id": "4537025176797184",
"isDelivered": true,
"subscription": "transfer",
"created": "2020-04-24T17:49:00.201602+00:00",
"log": {
"id": "5662318377566208",
"errors": [],
"type": "sending",
"created": "2020-04-24T17:49:09.751122+00:00",
"transfer": {
"id": "5950134772826112",
"accountNumber": "76543-8",
"amount": 100000000,
"bankCode": "665",
"branchCode": "2201",
"created": "2020-04-24T17:49:09.130246+00:00",
"fee": 200,
"name": "Daenerys Targaryen Stormborn",
"status": "processing",
"taxId": "594.739.480-42",
"tags": ["daenerys", "invoice/1234"],
"transactionIds": ["5991715760504832"],
"updated": "2020-04-24T17:49:02.130255+00:00",
}
},
"workspaceId": "1231231231231231
}
}Follow these recommendations to build a secure and resilient webhook integration.
Every event delivered to your webhook URL includes a header:
Digital-Signature
This signature is generated using Stark Bank's private key and can be verified using the public key available at:
GET /v2/public-key
Our SDKs handle this verification automatically when you use:
event.parse()
Never process events without verifying the signature first — this ensures the event was genuinely sent by Stark Bank and has not been tampered with.
Stark Bank sends webhook events from fixed IP addresses. Add them to your firewall ingress rules to block requests from unknown sources:
Production: 35.199.76.124, 34.85.188.162
Sandbox: 35.247.226.240, 35.245.182.229
Combining IP allowlisting with digital signature verification provides defense in depth for your webhook endpoint.
Your webhook handler should only do three things synchronously: validate the Digital Signature, save the event to your database, and return HTTP 200. Never process the event before returning 200.
All event processing — such as updating records, triggering payments, or sending notifications — must be done asynchronously in a segregated background task. Use a message queue or job scheduler to decouple receiving from processing.
If your endpoint does not return a 200 status, Stark Bank will retry the delivery according to the following schedule:
| Attempt | Delay |
|---|---|
| 1st retry | 5 minutes |
| 2nd retry | 30 minutes |
| 3rd retry | 120 minutes |
After 3 failed attempts, the delivery will stop. Use Event Polling to recover any missed events.
Events may be delivered more than once and are not guaranteed to arrive in order. Your handler must be idempotent — processing the same event twice should not cause incorrect behavior.
Guard against duplicates by logging processed event IDs and checking before processing. Do not rely on the order of event delivery — always check the current state of the resource rather than assuming a sequence.
This is especially critical for financial operations where duplicate processing could result in incorrect balances or duplicate payments.
Stark Bank may add new event types to webhooks at any time. Adding new events is not a breaking change.
Your webhook listener should gracefully handle unfamiliar event types — for example, by logging them and returning 200 — rather than failing or returning an error. This ensures your integration remains stable as the platform evolves.
More important than the order events arrive is observing the correct event to trigger your actions. Each resource goes through a lifecycle, and different events represent different stages.
For example, if you need an Invoice to be paid to complete a sale, wait for the paid event. But if you need the Invoice amount to be credited in your account before making a Transfer, wait for the credited event instead.
Reacting to the wrong event can lead to race conditions — such as trying to transfer funds that haven't been credited yet. Always match your business logic to the specific event that guarantees the precondition you need.
If your web framework enforces CSRF token validation (e.g. Django, Rails, Laravel), your webhook endpoint will reject Stark Bank's POST requests because they don't include a CSRF token.
Exempt your webhook route from CSRF protection. The Digital Signature verification already guarantees the request authenticity.
Stark Bank provides a full Sandbox environment that simulates the complete event lifecycle — creation, status changes, and webhook delivery — without real money.
Register your webhook URL in Sandbox, trigger operations (e.g. create an Invoice or Transfer), and verify that your endpoint receives and processes events correctly before going live.
Sandbox and Production use separate workspaces with different API keys. Webhooks registered in one environment will not receive events from the other.
Even with webhooks, we strongly recommend creating a daily task to:
1. Query all undelivered events using:
GET /v2/event?isDelivered=false
2. Process all undelivered events
3. Mark them as delivered using:
PATCH /v2/event/:id
isDelivered=true
This adds redundancy and resilience to your system, preventing you from having outdated information in case your system is temporarily unable to receive webhook events.