Record a transaction
Records a charge or refund the payment source took, under the source's own id for it.
Idempotent on externalId: the same request again returns the recorded transaction; correct a payment with a refund. Only a payment source records purchases.
Guide: Payment sources
A project secret key: vh_sk_... for production, vh_sk_test_... for test. Keep it on your servers.
In: header
Path parameters
The project's id, proj_.... A secret key works only in the project it belongs to.
The id of the project's payment provider connection, pp_conf_....
The payment source's own id for the transaction or subscription; to request a refund, the charge's.
Request body
application/json
TypeScript definitions
Use the request body type in TypeScript.
A charge or refund the payment source took. Amounts are integers in the currency's minor units.
charge for a payment, refund for money returned on a recorded charge.
Value in
- "charge"
- "refund"
The buyer's distinct id; a refund takes the charge's buyer. With customer as well, it identifies the source's customer as that person.
The buyer as the source's own customer; a charge requires it without distinctId; a refund takes the charge's buyer.
The source's key for the product paid for, as mapped to a product; required for a charge, a refund takes the charge's.
The amount charged or refunded, tax included, in the currency's minor units.
-9007199254740991 <= value <= 9007199254740991The ISO 4217 currency code; a refund's must match its charge's.
The source's commission, in minor units.
The tax included in amount, in minor units.
When the payment or refund happened, as an ISO 8601 timestamp.
The source's id for the subscription (see PUT .../subscriptions/{externalId}) whose period this charge pays for. Requires periodStart, periodEnd and a product that is a subscription.
The start of the subscription period a charge with subscriptionId pays for, as an ISO 8601 timestamp.
The end of the subscription period a charge with subscriptionId pays for, as an ISO 8601 timestamp.
The source's id for the charge a refund refunds; required for a refund.
production or test; defaults to production.
Examples
curl -X PUT "https://api.voidhash.com/api/v1/projects/proj_tz4a98xxat96iws9zmbrgj3a/payment-providers/pp_conf_m2c8v5n1x7z4q9w3e6r0t8y2/transactions/txn_20260314_0042" \ -H "Authorization: Bearer vh_sk_..." \ -H "Content-Type: application/json" \ -d '{ "type": "charge", "distinctId": "user_8231", "productKey": "pro-monthly", "amount": 499, "currency": "EUR", "tax": 80, "occurredAt": "2026-03-14T09:26:53.000Z", "subscriptionId": "sub_ext_0042", "periodStart": "2026-03-14T09:26:53.000Z", "periodEnd": "2026-04-14T09:26:53.000Z" }'{ "id": "txn_20260314_0042", "paymentProviderId": "pp_conf_m2c8v5n1x7z4q9w3e6r0t8y2", "type": "charge", "status": "applied", "pendingReason": null, "purchaseId": null, "bookedAmount": 499}{ "error": { "type": "invalid_request", "code": "invalid_transaction", "message": "Product pro_monthly is a subscription; its charges name the subscriptionId and period they pay for" }}{ "error": { "type": "unauthenticated", "code": "invalid_api_key", "message": "This secret key is not valid." }}{ "error": { "type": "permission_denied", "code": "permission_denied", "message": "Insufficient permissions." }}{ "error": { "type": "not_found", "code": "payment_provider_not_found", "message": "This project has no payment provider pp_conf_k2v8d4m1x7c9b3n6q0w5e2r8.", "param": "paymentProviderId" }}{ "error": { "type": "conflict", "code": "transaction_conflict", "message": "Transaction 1234567890 was already recorded with a different request; correct a payment with a refund" }}{ "error": { "type": "internal", "code": "internal_error", "message": "Something went wrong on our side. Try again, and contact support with the Request-Id header if it keeps failing." }}Response body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
Errors
| Status | type | code | When |
|---|---|---|---|
| 400 | invalid_request | invalid_transaction | For a transaction that cannot be recorded as sent, which records nothing. |
| 400 | invalid_request | payment_source_required | For a store. |
| 404 | not_found | payment_provider_not_found | For an unknown provider. |
| 409 | conflict | transaction_conflict | For a different request with the same externalId. |
| 409 | conflict | payment_source_disabled | For a disabled source. |
It can also fail with the errors every operation shares, such as unauthenticated; see Errors.
More in Payment sources
- Refund a transaction
POST - Record a subscription
PUT - Cancel a subscription
POST
Something wrong or missing on this page? Tell us by email or on Discord.