POST notification whenever something relevant happens.
This module gives you full control over:
Where to receive
Configure your own webhook URL.
Which events
Select from the available transaction categories.
Delivery monitoring
Inspect recent events, delivery attempts, and your server’s responses.
Available endpoints
Authenticating requests to these endpoints
Every request toGET /api/businesses/webhooks, PUT /api/businesses/webhooks, and GET /api/businesses/events requires the following headers:
Requests without these headers, or signed with the webhook-verification formula, will fail:
- No headers at all →
401, generic error. - Correct headers but wrong signature formula →
422,"Invalid signature".
Webhook signature calculation
Vita signs every webhook notification it sends to your server using an HMAC-SHA256 signature. The signature lets you verify that the request truly comes from Vita Business and that its content hasn’t been modified in transit. It’s calculated using yourbusiness_secret and is included in the Authorization header alongside a timestamp in the X-Date header. Your server must reconstruct and validate this signature on every webhook delivery before processing the payload.
Required credentials
Signature calculation process
Formula1
Obtain x_login
The hexadecimal hash provided by Vita Business.
2
Generate x_date
ISO 8601 timestamp with timezone.
3
Build the data hash
Use the event structure (see below).
4
Convert to compact JSON
No spaces, no line breaks.
5
Concatenate directly
x_login + x_date + compact_json — no separators.6
Calculate HMAC-SHA256
Using your
business_secret as the key.7
Send the signature
In the
Authorization header.Data hash structure
The data hash contains the following top-level fields:About
event_id. Despite its name and the UUID-like appearance in examples, this is an opaque text identifier, not a validated UUID. Most real values carry an extra numeric suffix (e.g. f3065db9-1a97-493a-a8c2-97cbb84bf889-24544). Do not validate its format — treat it as an opaque string.Worked example
Inputsx_login:f2fe62688115b98e060533145ca6c32ec070bb9ex_date:2026-01-15T14:27:47+00:00business_secret:[your_secret_key]
business_secret. Message: the full string from step 2. Output: a 64-character hexadecimal signature.
Step 4 — Final HTTP request headers:
How to validate an incoming signature
1
Extract x_date
From the
X-Date header.2
Use your x_login
Stored on your side.
3
Take the received JSON body exactly as-is
Do not modify, reformat, reorder, or re-serialize it.
4
Reconstruct string_to_sign
x_login + x_date + body_json.5
Calculate the expected signature
HMAC-SHA256 with your
business_secret.6
Compare
With the one received in the
Authorization header (after V2-HMAC-SHA256, Signature:).7
Accept or reject
If the signatures match, the webhook is authentic. If they don’t, reject the request.
Important notes
x_loginis a hexadecimal hash (40 characters in the example above).- The JSON of the data hash is always compact — no spaces, no line breaks.
x_datemust be ISO 8601 with timezone (e.g.,2026-01-15T14:27:47+00:00).- Concatenation is direct, with no separators:
x_login + x_date + json_string. - Authorization header format:
V2-HMAC-SHA256, Signature: {signature}. - The
x_dateused in the signature must match exactly theX-Dateheader sent in the request. - The resulting signature is a 64-character hexadecimal hash.
- Use the body as received — never re-serialize the JSON before validating, as it may change byte-for-byte.
API status reference
This reference describes all statuses used across Vita, organized by the entity they apply to:- Payment Orders — used in Payins for collecting funds.
- Payment Order Attempts — individual payment trials within a Payment Order.
- Transactions — internal fund movements used in both Payins and Payouts.
Payins
Payment Order
A Payment Order is a payment request created to collect funds from a customer. It represents the entire payment lifecycle and can contain one or more attempts. Each Payment Order has:- A unique identifier (
public_codeorissue). - An expiration date.
- A final status reflecting the overall outcome of the collection process.
Who can cancel a Payment Order. You (the client) cannot cancel a Payment Order through the API — there is no cancel operation exposed. However, Vita can cancel a Payment Order internally for operational or compliance reasons. When that happens, you receive a
payment_order.cancelled webhook and the order’s final status becomes cancelled. Build your integration to handle this event and status explicitly — do not treat cancelled as an impossible or invalid state.Payment Order Attempt
A Payment Order Attempt represents a single trial by the user to fulfill a Payment Order. Since users may run into issues during checkout — declined cards, insufficient funds, closed browser — each session or transaction try is logged as a separate Attempt. This structure gives you a granular history: while several attempts might fail or be cancelled, the parent Payment Order remains valid until one attempt succeeds, the order is cancelled by Vita, or the overall time limit elapses. Understanding the relationship- A single Payment Order can contain multiple (N) Payment Order Attempts.
- A
payment_order_attempt.cancelledevent does not mean the payment link is cancelled — it only means that specific attempt failed. - A user may start a new attempt after a failure, which could eventually move the Payment Order to
paid.
public_code or issue of the order):
payment_order.paidpayment_order_attempt.paid
payment_order.expired— the link’s time limit elapsed without payment.payment_order.cancelled— Vita cancelled the order internally.
Payment Order and Payment Order Attempt event payloads
These payloads carry payer and payment-specific data (payer name, document, amount, currency, on-hold-related fields, spread, fixed cost, country code, and more) rather than the transaction-category attributes described further below. Match incoming events to your internal records usingpublic_code or issue.
A full field-by-field reference for
payment_order.* and payment_order_attempt.* payloads is pending — request the current schema from your integration contact if you need it before it’s published here.Payment Order statuses
Payment Order Attempt statuses
Payment Order Attempts use the same statuses as Payment Orders, applied to the specific attempt:A
cancelled attempt does not cancel the parent Payment Order. A new attempt may still be initiated.Transactions
Transactions track the internal movement of funds within Vita and are used in both Payins and Payouts (withdrawals, Vita Sent, crypto payouts, exchanges, etc.).Transaction statuses
Status lifecycles at a glance
Payment Order lifecycle Transaction lifecycleImportant considerations
Webhooks drive status updates
Webhooks drive status updates
All status changes are communicated via Webhooks. Configure your webhook URL and category subscriptions to ensure you receive real-time updates.
Match by public_code or issue
Match by public_code or issue
For Payment Orders, always match incoming webhook events to your internal records using
public_code or issue. Both payment_order.* and payment_order_attempt.* events relate to the same underlying order — and both require the payment category subscription.A cancelled attempt is not a cancelled order
A cancelled attempt is not a cancelled order
This is one of the most common misinterpretations. A
payment_order_attempt.cancelled event affects only that attempt — the parent order remains valid until it’s paid, expired, or cancelled by Vita.Final vs. intermediate statuses
Final vs. intermediate statuses
- Final (terminal):
paid,expired,cancelled,reimbursed,completed,denied,failed,time_out. - Intermediate:
pending,checking,processed,started,on_hold,reimbursing.