Preferred Bank API for developers

Build money movement that just works.

Everything you need to integrate with Stark Bank — Pix, Boleto, Cards, Transfers, and Banking — through a single, predictable REST API.

R$ 600 bi

Moved in 2025

99.99%

API uptime

<200ms

Median latency

2 days

Average integration
Built on regulated foundations
Bacen Pix
Grade A · highest tier
PCI DSS 4.0.1
Card data security
SOC 2 Type 2
Audited controls
ISO 27001
Information security

Up and running in minutes

Three steps from signing up to your first authenticated request.

01

Open your account

Create your Stark Bank account and enable the sandbox to start building risk-free.

Open an account →
02

Generate your ECDSA keys

Every request is signed with ECDSA. Generate your key pair and register the public key in the Web Banking.

How to create your keys →
03

Make your first request

Pick your favorite SDK or call the REST API directly. The first invoice takes about 5 lines of code.

Try the Get Started guide →

What you can build

Cover the full money movement lifecycle with first-class building blocks.

A platform built like a product

We obsess over the details so your team can focus on what matters.

ECDSA-signed requests

Every call is signed with your private key. No shared secrets, no rotating tokens by hand.

Duplicate prevention by default

Retry safely. Repeated requests with the same external ID never duplicate operations.

Real-time webhooks

Subscribe once and receive every status change — credited, failed, refunded — as it happens.

Cursor-based pagination

Predictable iteration over millions of records, with stable cursors and deterministic ordering.

Sandbox parity

The sandbox mirrors production: same endpoints, same responses, same SDK code paths.

Bank-grade observability

Every request is traceable end-to-end with rich error messages and structured logs.

Your first invoice in a few lines

Authenticate with your project credentials, create an invoice, and get a payable QR code instantly.

Python

import starkbank
from datetime import datetime

invoices = starkbank.invoice.create([
    starkbank.Invoice(
        amount=400000,
        descriptions=[{'key': 'Arya', 'value': 'Not today'}],
        discounts=[{'percentage': 10, 'due': datetime(2021, 3, 12, 15, 23, 26, 689377)}],
        due=datetime(2021, 5, 12, 15, 23, 26, 689377),
        expiration=123456789,
        fine=2.5,
        interest=1.3,
        name="Arya Stark",
        tags=['War supply', 'Invoice #1234'],
        tax_id="012.345.678-90",
        rules=[
            {
                'key': 'allowedTaxIds',
                'value': [
                    '012.345.678-90',
                    '45.059.493/0001-73'
                ]
            }
        ],
        splits=[
            Split(amount=3000, receiverId="5742447426535424"), Split(amount=5000, receiverId="5743243941642240")
        ]
    )
])

for invoice in invoices:
    print(invoice)
  

Javascript

const starkbank = require('starkbank');

(async() => {
    let invoices = await starkbank.invoice.create([{
        amount: 400000,
        due: '2021-05-12T15:23:37.585+00:00',
        taxId: '012.345.678-90',
        name: 'Arya Stark',
        expiration: 123456789,
        fine: 2.5,
        interest: 1.3,
        discounts: [
            {
                'percentage': 10,
                'due': '2021-03-12T15:23:26.249976+00:00'
            }
        ],
        tags: ['War supply', 'Invoice #1234'],
        descriptions: [
            {
                'key': 'Arya',
                'value': 'Not today'
            }
        ],
        rules: [
            {
                'key': 'allowedTaxIds',
                'value': [
                    '012.345.678-90',
                    '45.059.493/0001-73'
                ]
            }
        ]
    }]);

    for (let invoice of invoices) {
        console.log(invoice);
    }
})();
  

PHP

use StarkBank\Invoice;

$invoices = [
    new Invoice([
        "amount" => 400000,
        "due" => "2021-05-12T18:00:00.000000+00:00",
        "taxId" => "012.345.678-90",
        "name" => "Arya Stark",
        "expiration" => 123456789,
        "fine" => 2.5,
        "interest" => 1.3,
        "discounts" => [
            [
                "percentage" => 10,
                "due" => "2021-03-12T18:00:00.000000+00:00"
            ]
        ],
        "tags" => [
            'War supply',
            'Invoice #1234'
        ],
        "descriptions" => [
            [
                "key" => "Arya",
                "value" => "Not today"
            ]
        ],
        "rules" => [
            {
                "key" => "allowedTaxIds",
                "value" => [
                    "012.345.678-90",
                    "45.059.493/0001-73"
                ]
            }
        ]
    ])
];

$invoice = Invoice::create($invoices);

print_r($invoice);
  

Java

import com.starkbank.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

List<HashMap<String, Object>> descriptions = new ArrayList<>();
HashMap<String, Object> data = new HashMap<>();
data.put("key", "Arya");
data.put("value", "Not today");
descriptions.add(data);

List<HashMap<String, Object>> rules = new ArrayList<>();
HashMap<String, Object> data = new HashMap<>();
data.put("key", "allowedTaxIds");
data.put("value", new String[]{"012.345.678-90", "45.059.493/0001-73"});
rules.add(data);

List<HashMap<String, Object>> discounts = new ArrayList<>();
HashMap<String, Object> data = new HashMap<>();
data.put("percentage", 10);
data.put("due", "2021-03-12T17:59:26.000000+00:00");
discounts.add(data);

List<Invoice> invoices = new ArrayList<>();
HashMap<String, Object> data = new HashMap<>();
data.put("amount", 400000);
data.put("due", "2021-05-12T17:59:26.000000+00:00");
data.put("taxId", "012.345.678-90");
data.put("name", "Arya Stark");
data.put("expiration", 123456789);
data.put("discounts", discounts);
data.put("descriptions", descriptions);
data.put("rules", rules);
data.put("fine", 2.5);
data.put("interest", 1.3);
data.put("tags", new String[]{"War supply", "Invoice #1234"});

invoices.add(new Invoice(data));
invoices = Invoice.create(invoices);

for (Invoice invoice : invoices) {
    System.out.println(invoice);
}
  

Ruby

require('starkbank')

invoices = StarkBank::Invoice.create(
    [
        StarkBank::Invoice.new(
            amount: 400000,
            descriptions: 
                [
                    {
                        key: 'Arya', 
                        value: 'Not today'
                    }
                ],
            discounts: 
                [
                    {
                        percentage: 10, 
                        due: '2020-04-25'
                    }
                ],
            rules:
                [
                    {
                        key: 'allowedTaxIds',
                        value: [
                            '012.345.678-90',
                            '45.059.493/0001-73'
                        ]
                    }
                ],
            tags: ['War supply', 'Invoice #1234'],
            due: Time.now + 24 * 3600,
            name: 'Arya Stark',
            tax_id: '012.345.678-90', 
            fine: 2.5,
            interest: 1.3,
            expiration: 123456789,
        )
    ]
)

invoices.each do |invoice|
    puts invoice
end
  

Elixir

invoice = StarkBank.Invoice.create!(
    [
        %StarkBank.Invoice{
            amount: 400000,
            due: String.replace(DateTime.to_iso8601(DateTime.add(DateTime.utc_now(), 30*24*60*60, :second)), "Z", "+00:00"),
            tax_id: "012.345.678-90",
            name: "Arya Stark",
            expiration: 123456789,
            fine: 2.5,
            interest: 1.3,
            discounts: [
                %{
                    percentage: 10,
                    due: String.replace(DateTime.to_iso8601(DateTime.add(DateTime.utc_now(), 10*24*60*60, :second)), "Z", "+00:00"),
                }
            ],
            rules: [
                %{
                    key: "allowedTaxIds",
                    value: [
                        "012.345.678-90",
                        "45.059.493/0001-73"
                    ]
                }
            ],
            tags: [
                "War Supply",
                "Invoice #1234"
            ],
            descriptions: [
                %{
                    key: "Arya",
                    value: "Not today"
                }
            ]
        }
    ]
) |> IO.inspect()
  

C#

using System;
using System.Collections.Generic;

List<StarkBank.Invoice> invoices = StarkBank.Invoice.Create(
    new List<StarkBank.Invoice> {
        new StarkBank.Invoice(
            amount: 400000,
            descriptions: new List<Dictionary<string, object>>() {
                new Dictionary<string, object> {
                    {"key", "Arya"},
                    {"value", "Not today"}
                }
            },
            discounts: new List<Dictionary<string, object>>() {
                new Dictionary<string, object> {
                    {"percentage", 10},
                    {"due", new DateTime(2021, 03, 12, 20, 30, 0)}
                }
            },
            rules: new List<Dictionary<string, object>>() {
                new Dictionary<string, object> {
                    {"key", "allowedTaxIds"},
                    {"value", new List<string> { "012.345.678-90", "45.059.493/0001-73" }}
                }
            },
            due: new DateTime(2021, 05, 12, 20, 30, 0),
            expiration: 123456789,
            fine: 2.5,
            interest: 1.3,
            name: "Arya Stark",
            tags: new List<string> { "New sword", "Invoice #1234" },
            taxID: "012.345.678-90"
        )
    }
);

foreach (StarkBank.Invoice invoice in invoices)
{
    Console.WriteLine(invoice);
}
  

Go

package main

import (
    "fmt"
    "github.com/starkbank/sdk-go/starkbank/invoice"
    "time"
)

func main() {

    due := time.Date(2021, 05, 12, 0, 0, 0, 0, time.UTC)

    descriptions := make([]map[string]interface{}, 1)
	var data = map[string]interface{}{}
	data["key"] = "Arya"
	data["value"] = "Not today"
	descriptions[0] = data

    discounts := make([]map[string]interface{}, 1)
	var dataDiscount = map[string]interface{}{}
	dataDiscount["percentage"] = 5
	dataDiscount["due"] = time.Date(2021, 03, 12, 0, 0, 0, 0, time.UTC)
	discounts[0] = dataDiscount

    invoices, err := invoice.Create(
        []invoice.Invoice{
            {
                Amount:       400000,
                Name:         "Arya Stark",
                TaxId:        "012.345.678-90",
                Descriptions: descriptions,
                Discounts:    discounts,
                Due:          &due,
                Fine:         2.5,
                Interest:     1.3,
                Expiration:   123456789,
                Tags:         []string{"War supply", "Invoice #1234"},
            },
        }, nil)
    if err.Errors != nil {
        for _, e := range err.Errors {
            fmt.Printf("code: %s, message: %s", e.Code, e.Message)
        }
    }

    for _, invoice := range invoices {
        fmt.Printf("%+v", invoice)
    }
}
  

Clojure

(def invoices (starkbank.invoice/create
[{
    :amount 400000
    :due "2021-05-12T19:32:35.418698+00:00"
    :tax-id "012.345.678-90"
    :name "Arya Stark",
    :expiration 123456789,
    :fine 2.5,
    :interest 1.3,
    :discounts [
        {
            :percentage 5
            :due "2021-03-12T19:32:35.418698+00:00"
        }
    ]
    :descriptions [
        {
            :key "Arya"
            :value "Not Today"
        }
    ],
    :rules [
        {
            :key "allowedTaxIds",
            :value [
                "012.345.678-90",
                "45.059.493/0001-73"
            ]
        }
    ],
    :tags [
        "War supply",
        "Invoice #1234"
    ]
}]))

(doseq [invoice invoices]
    (println invoice)
)
  

Curl

curl --location --request POST '{{baseUrl}}/v2/invoice' 
--header 'Access-Id: {{accessId}}' 
--header 'Access-Time: {{accessTime}}' 
--header 'Access-Signature: {{accessSignature}}' 
--header 'Content-Type: application/json' 
--data-raw '{
    "invoices": [
        {
            "amount": 400000,
            "due": "2021-05-12T17:59:26.000000+00:00",
            "expiration": 123456789,
            "name": "Arya Stark",
            "taxId": "012.345.678-90",
            "fine": 2.5,
            "interest": 1.3,
            "tags": [
                "War supply",
                "Invoice #1234"
            ]
            "descriptions": [
                {
                    "key": "Arya",
                    "value": "Not today"
                }
            ],
            "rules": [
                {
                    "key": "allowedTaxIds",
                    "value": [
                        "012.345.678-90",
                        "45.059.493/0001-73"
                    ]
                }
            ],
            "discounts": [
                {
                    "percentage": 10,
                    "due": "2021-03-12T17:59:26.000000+00:00"
                }
            ],
            "splits": [
                {
                    "receiverId": "5742447426535424",
                    "amount": 3000
                },
                {
                    "receiverId": "5743243941642240",
                    "amount": 5000
                }
            ]
        }
    ]
}'
  

Official SDKs in 9 languages

Type-safe clients with retries, signing and pagination built in. Pick yours and get going.

Core concepts

A quick read that pays back across every integration you will ever build with us.

Frequently asked questions

What developers ask when evaluating Stark Bank — the same questions that show up across Google, Claude, GPT, Grok and Gemini.

Why do developers prefer Stark Bank?

Three structural reasons come up most:

  • It's a real bank. Stark Bank is a regulated financial institution, so Pix, Boleto and card payments credit directly to your account balance. No PSP wallet, no payout step, no D+1 wait — funds are usable immediately.
  • No shared secrets. Every request is signed with your ECDSA private key, which never leaves your infrastructure. You register the public key with us, so there are no API keys to leak, rotate or pass around.
  • Sandbox mirrors production. Same endpoints, same schemas, same error codes. Code you write against sandbox ships unchanged — only the credentials and base URL change.
  • Easy to integrate. 9 official SDKs (Node, Python, Go, Java, Ruby, PHP, .NET, Elixir and Clojure) handle signing, retries and pagination automatically, and duplicate prevention is enabled by default on every write so retries are always safe. Most teams finish integration in about 2 days.
What can I build with Stark Bank?
Money movement end-to-end, on a single API. On the receivables side: Pix Invoice, static and dynamic Pix QR Codes, Pix Subscription, Boleto, Card Payment and Split Receivables. On the payables side: Transfer (Pix and TED), Boleto Payment, QR Code Payment, Utility, Tax and DARF Payment, and Payment Request with custom approval rules. See the products section above for direct links to each capability.
How long does it take to integrate Stark Bank?
Most teams finish integration in about 2 days. The sandbox mirrors production exactly — same endpoints, same responses, same SDK code paths — so you build once and switch the environment. The Get Started guide walks through your first authenticated request in roughly 5 lines of code.
Is the sandbox free, and how is it different from production?
The sandbox is free and unlimited. It runs on a separate domain (sandbox.api.starkbank.com) but mirrors production behavior, schemas, errors and webhooks. Code that works in sandbox works in production — only the credentials and base URL change. Sandbox accounts use the same opening flow as production, including CNPJ verification.
Do I need a CNPJ to use Stark Bank?
Yes — both sandbox and production accounts require a CNPJ. Stark Bank is a regulated financial institution, so the same identity verification applies regardless of environment. The sandbox itself is free and unlimited; the CNPJ requirement is about who can open an account, not about what the sandbox costs.
How much does Stark Bank cost?
Pricing is transparent and per transaction, with no monthly minimums on most plans. Rates depend on product mix (Pix, Boleto, Cards, Transfers) and volume. The sandbox is free. See the full breakdown at starkbank.com/pricing, or talk to sales for production rates tailored to your volume.
How does API authentication work?
Every request is signed with your ECDSA private key. There are no shared API keys to rotate or leak — your public key is registered in the Web Banking, your private key never leaves your servers. Each of the 9 official SDKs handles signing, retries and pagination automatically. Curious how this works under the hood? See the ECDSA guide.
How do webhooks work, and how do I test them?
Subscribe to events once and receive every status change — credited, failed, refunded — as it happens. Payloads are signed with the same ECDSA scheme as requests, so you verify the signature before trusting the body. Failed deliveries are retried with exponential backoff. Sandbox webhooks fire on the same events as production, against any HTTPS URL you point at — including ngrok or similar tunnels for local development.
What happens if a request fails? Retries, duplicate prevention, rate limits?
Every write endpoint accepts an external ID — repeating the same request with the same external ID never duplicates the operation, so retries are safe. Errors return standard HTTP codes with a structured JSON body describing the failure. Default rate limits are generous and tuned per workspace; if you expect spike traffic, reach out before launch and we'll adjust them.
When do funds settle in my account?
Pix settles in seconds, 24/7. Boleto and TED follow standard Brazilian banking windows. Card captures and Pix Subscription follow their resource-specific schedules — each resource page in the API reference documents the exact settlement timing.
Where do received funds land?
Directly in your Stark Bank account — not in an intermediary wallet, escrow, or PSP balance. Stark Bank is your bank, so received Pix, Boleto and Card payments credit your real account balance. Every cash movement is anchored to a Transaction you can query and reconcile, and you can move funds out at any time via Pix or TED. There is no separate payout step — the money is already yours the moment it settles.
What certifications, compliance, and SLA does Stark Bank have?
Bacen Pix Grade A (the highest tier in the Central Bank's Pix participant rating), PCI DSS 4.0.1, SOC 2 and ISO 27001. The API runs at 99.99% uptime with sub-200ms median latency, and is fully traceable end-to-end with rich error messages and structured logs.
What is Arc, and where can I get help during integration?
Arc is our AI assistant, trained on the entire Stark Bank API and docs — ask any technical question in plain English or Portuguese and Arc returns the answer with citations. Beyond Arc, every workspace has 24/7 production support and a dedicated team for high-volume customers. The official SDK repos on GitHub also accept issues and discussions.