ROKIConnect

Verified traps

12.1 Unknown fields are silently ignored

A body with a misspelled field name returns 201 Created with no warning, and the payment is created without that feature.

{ "amount": 100, "service_fee": true }     <- wrong name
-> 201 Created, service_fee_amount: 0       <- the fee pass-through was NOT applied

This is the most dangerous failure mode of the API, because the result looks successful. It is especially dangerous for AI-generated code, which tends to write other gateways' field names (card_token, payment_method, customer_id, amount_cents) with full confidence.

Mandatory defence: after creating a payment, verify in the response that the computed fields (sales_tax_amount, service_fee_amount, total, reusable) match what you expected. And validate your request body against the schema in openapi.yaml, which declares additionalProperties: false precisely to catch what the API lets through.

12.2 amount has no ceiling and coerces types

The API accepts absurd amounts (11 digits) and numeric strings ("150.00"). Enforce a sane maximum before sending.

12.3 Two different kinds of 404

Response Meaning
{"message":"Pago no encontrado."} The route exists; the payment does not. Wrong id, or an id from the other environment.
{"message":"The route ... could not be found."} The route does not exist. Malformed URL or a nonexistent endpoint.

Telling them apart saves hours: the second is never fixed by changing the id.

12.4 Timestamps are Honduras local time with no offset

expires_at, created_at and paid_at come back as YYYY-MM-DD HH:MM:SS in Honduras time (UTC-6), with no timezone marker in the string. Parsing them as UTC shifts every value by six hours - enough to make a future expiry look expired, or an order look paid before it was created. Attach the offset explicitly when parsing.

12.5 A customer-selected tip is not in the total you were given

With tip_customer_selectable, the total returned at creation excludes the tip because the customer has not chosen it yet. The amount actually charged can therefore be higher than the total you stored. Reconcile against the webhook payload or a fresh lookup, never against the creation response.

12.6 metadata can come back as an empty array

When no metadata was sent, the API may return "metadata": [] instead of {}. Strict deserializers that expect an object will throw. Treat both shapes as "no metadata".

12.7 Do not hardcode the checkout domain from the official docs

The checkout_url returned is on aura.roki.systems/pay/link/{slug}. Never hardcode or allow-list a checkout domain - always redirect to the exact checkout_url the API returned.

12.8 success_url accepts http://

Although the official documentation requires HTTPS, the API accepts unencrypted URLs. Use HTTPS anyway - it is a return URL in a payment flow.