Upload the CSD
LiveServed by the v1 API in development with the same checks as production; production opens on the same contract. The capabilities from before v1 keep running in production at the path your account team gives you.
Uploads or replaces the merchant's CSD from your back end, for integrations that already hold it. Prefer the onboarding page when you can: with it you never handle the merchant's certificate or password.
heru checks the files and calculates the merchant status from the certificate dates. When a check fails it answers 422 and keeps the current CSD; every code is explained in CSD errors.
Needs the merchants:csd scope.
oauth2 merchants:csdAuthorizationBearer <token>OAuth 2.0 client credentials. Exchange your client_id and client_secret at /oauth/token of the environment for a bearer token valid for one hour. The playground of every operation asks for your own client and keeps it in your browser tab only.
Scope: merchants:csd
id*stringThe merchant id.
^mer_[0-7][0-9a-hjkmnp-tv-z]{25}$multipart/form-data- body
certificate*fileThe CSD certificate, the .cer file.
binaryprivate_key*fileThe CSD private key, the .key file.
binarypassword*stringPassword of the private key. heru stores it encrypted with the key and never returns it.
passwordThe CSD was accepted.
application/json- response
status*stringMerchant status after the upload, calculated from the certificate: active when it is valid for more than 30 days, csd_expiring when it expires within 30 days.
"active""csd_expiring"message*stringcsd*curl -X PUT 'https://api.dev.b2b.heru.app/v1/merchants/mer_01m4ra8wsyfh3s0tr4nrq3y96j/csd' \ -F 'certificate=string' \ -F 'private_key=string' \ -F 'password=pa$$word'{ "status": "active", "message": "CSD accepted. The merchant can invoice.", "csd": { "serial_number": "00001000000712345678", "valid_from": "2026-10-14", "valid_to": "2030-10-14" }}Void a chargePOST
Use it when the card payment is reversed before the customer invoices: a wrong amount, a refund or a bank reversal. The charge becomes `void`, its link stops working and it never goes into the global invoice. If the customer already invoiced it, cancel the invoice instead; this answers `409`. A charge that expired or was already voided answers `410`. Needs the `charges:void` scope.
List merchantsGET
Merchants of your company, most recent first. Needs the `merchants:read` scope.