# Core Concepts

Before diving into specific resources, it helps to understand a few concepts that appear across the entire Stark Bank API.

Tags, metadata, and transaction IDs are fields shared by most resources. Understanding how they work will help you build cleaner integrations and simplify reconciliation.

This guide also covers duplicate prevention — a critical pattern for safely retrying requests in financial APIs — and best practices for linking your internal records to Stark Bank operations.

**CONCEPT SUMMARY**

TagsLabel operations with custom strings for filtering and reconciliation.MetadataAttach arbitrary key-value data to operations.Transaction IDsTrace operations to their ledger statement entries.Duplicate PreventionSafely retry requests without creating duplicates.Best PracticesRecommendations for ID management, reconciliation, and performance.

## Tags

Tags are arrays of strings that you can attach to almost any operation in the Stark Bank API. They allow you to label, filter, and reconcile operations using your own identifiers.

### What are Tags

Tags are a list of strings available as a parameter on most Stark Bank resources, including Transfers, Invoices, Boletos, Deposits, and Payments.

You can add any string values you want. Common examples include your internal order ID, customer ID, cost center, or any label that helps you organize operations.

All tags are automatically converted to lowercase, so "Order123" and "order123" are treated as the same tag.

### Tags in the Statement

When an operation generates a statement entry (Transaction), the tags you assigned to that operation are carried over to the corresponding Transaction.

This means you can search your bank statement using your own internal IDs, making it easy to match statement entries to your business records.

### Filtering by Tags

You can filter most list endpoints by tags. For example, when listing Transfers, you can pass one or more tags to retrieve only the operations you labeled with those strings.

This is especially useful for reconciliation — if you tag every operation with your internal order ID, you can instantly find the corresponding Stark Bank operation later.

### Tags in Webhooks

Tags are included in webhook event payloads. When you receive a webhook notification about an operation, the tags you originally assigned will be present in the event data.

This allows your webhook handler to immediately identify the business context of an event without making an additional API call.

## Metadata

Metadata is a general-purpose key-value dictionary that you can attach to operations. It allows you to store structured data alongside your Stark Bank resources.

### What is Metadata

Metadata is a dictionary (JSON object) that you can include when creating certain operations. Unlike tags, which are simple strings, metadata supports structured key-value pairs.

The metadata you attach is stored by Stark Bank and returned whenever you query the resource. It is not used by Stark Bank internally — it exists purely for your convenience.

### Use Cases

Common uses for metadata include:

Internal references: Store your internal order ID, customer ID, or any identifier that links back to your system.

Audit trails: Record which user or system initiated the operation.

Business context: Attach information like department, project, or cost center.

Metadata gives you flexibility to store whatever context you need alongside the operation, without having to maintain a separate mapping in your own database.

### How Metadata Works

Pass the metadata dictionary when creating a resource. The entire dictionary is stored and returned as-is on subsequent GET requests.

Metadata is not indexed for filtering. If you need to search by a value, use tags instead. Metadata is best for storing contextual information that you retrieve along with the resource.

You can store strings, numbers, booleans, and nested objects within metadata. There is no strict schema — the structure is entirely up to you.

## Transaction IDs

Transaction IDs connect your operations to the bank statement. Every cash-in or cash-out operation generates ledger entries, and transactionIds tells you exactly which statement entries correspond to a given operation.

### What are Transaction IDs

Every operation that moves money — whether it is a cash-in (like a Deposit or Invoice payment) or a cash-out (like a Transfer or Boleto Payment) — generates one or more entries in your bank statement.

Each statement entry is a Transaction resource with its own unique ID. The transactionIds field on the operation contains a list of these Transaction IDs.

This field is read-only and is populated once the operation has been processed and the corresponding statement entries have been created.

### Reconciling with the Statement

The transactionIds field is the bridge between your operations and your bank statement. With it, you can:

1. Start from an operation (e.g., a Transfer) and find the exact statement entries it generated.

2. Start from a statement entry (Transaction) and trace it back to the operation that created it.

This bidirectional link is essential for financial reconciliation, auditing, and accounting.

### Where Transaction IDs Appear

The transactionIds field is available on most resources that generate statement movement, including:

Transfers, Deposits, Invoices, Boleto Payments, Utility Payments, Tax Payments, and more.

The field contains a list because some operations may generate multiple statement entries — for example, an operation and its fee may be separate transactions.

## Duplicate Prevention

Duplicate prevention ensures that retrying a request does not create duplicate operations. This is critical in financial APIs where network failures can leave you uncertain whether a request succeeded.

### Why Duplicate Prevention Matters

Imagine you create a Transfer, but your connection drops before you receive the response. Did the Transfer go through? If you simply retry the request, you might create a second Transfer and move funds twice.

Duplicate prevention solves this problem. By including a unique identifier with your request, Stark Bank can recognize duplicate submissions and reject the second one instead of creating a new operation.

### Using External IDs

Many Stark Bank resources accept an externalId parameter. This should be a unique string generated by your system — such as a UUID or your internal order ID.

If you send a creation request with an externalId that has already been used, the API will not create a duplicate. Instead, it will return an error so you can recover the original resource by querying with that externalId.

Always generate the externalId before making the request and persist it in your database. This way, if you need to retry, you can send the same externalId and safely prevent duplicates.

### Best Practices for Duplicate Prevention

Use a unique externalId for every distinct operation. Do not reuse externalIds across different operations.

Generate the externalId on your side before calling the API. UUIDs (v4) are a reliable choice.

Store the externalId alongside the operation in your database so you can correlate retries and responses.

Combine duplicate prevention with tags for maximum traceability: use the externalId for duplicate prevention and tags for filtering and reconciliation.

## Best Practices

Follow these recommendations to build robust integrations that are easy to reconcile and debug.

### Always Save Stark Bank IDs

Every resource created through the Stark Bank API returns a unique id. Always save this ID in your database immediately after receiving the creation response.

The Stark Bank ID is the primary key for querying, updating, and referencing the resource in future API calls. Losing it means you will need to search for the resource by other means.

### Put Your IDs in Tags

When creating an operation, include your internal identifiers (order ID, customer ID, etc.) in the tags parameter.

This creates a two-way link: your database holds the Stark Bank ID, and the Stark Bank resource holds your internal IDs. You can search from either direction.

For example, if a customer calls about order #12345, you can list Transfers filtered by the tag "order-12345" to instantly find the corresponding operation.

### Reconciliation Strategy

A complete reconciliation strategy uses all three concepts together:

1. Tags: Store your internal IDs on each operation for easy lookup and filtering.

2. Transaction IDs: Link operations to your bank statement entries for accounting.

3. Saved IDs: Keep Stark Bank's ID in your database to query specific operations directly.

With this approach, you can trace any operation from your internal system to the bank statement and back.

### Prefer Webhooks Over Polling

Do not loop or poll the API to check for status changes. Polling wastes API calls, increases latency, and puts unnecessary load on both your system and the API.

Instead, use webhooks to receive real-time notifications whenever an operation changes status. Webhooks are pushed to your server the moment an event occurs — no delay, no wasted requests.

Polling should only be used as a fallback safety net. For example, a daily job that queries for undelivered events ensures your system stays up to date if a webhook is missed due to temporary downtime.

See the Webhook Get Started guide for detailed implementation instructions.

### Combine Webhooks with Polling for Resilience

Webhooks give you real-time notifications, but they are not guaranteed to be delivered — your server might be down, or a network issue might occur.

Always complement webhooks with a periodic polling job that queries for undelivered events. This ensures your system stays up to date even if a webhook is missed.

The recommended pattern is: use webhooks as the primary channel for real-time updates and run a daily reconciliation job using the Event endpoint to catch anything that slipped through.

See the Webhook Get Started guide for best practices on handling webhook events reliably.

---

## Other Languages

- [Python](https://docs.starkbank.com/get-started/core-concepts-python.md)
- [Node.js](https://docs.starkbank.com/get-started/core-concepts-node.md)
- [PHP](https://docs.starkbank.com/get-started/core-concepts-php.md)
- [Java](https://docs.starkbank.com/get-started/core-concepts-java.md)
- [Ruby](https://docs.starkbank.com/get-started/core-concepts-ruby.md)
- [Elixir](https://docs.starkbank.com/get-started/core-concepts-elixir.md)
- [.NET](https://docs.starkbank.com/get-started/core-concepts-dotnet.md)
- [Go](https://docs.starkbank.com/get-started/core-concepts-go.md)
- [Clojure](https://docs.starkbank.com/get-started/core-concepts-clojure.md)
- [cURL](https://docs.starkbank.com/get-started/core-concepts-curl.md)
