Developers

API Reference

A resource-oriented REST API over HTTPS. Predictable URLs, JSON request and response bodies, standard verbs, and errors you can act on programmatically.

Base URL and conventions

Everything lives under two hosts. The sandbox mirrors production exactly — same endpoints, same objects, same failure modes — so you can build against it with confidence and switch by changing one key.

EnvironmentBase URLKey prefix
Sandboxhttps://api.sandbox.bearmerchant.comsk_test_…
Productionhttps://api.bearmerchant.comsk_live_…
  • All requests must be made over HTTPS. Plain HTTP is rejected, not redirected.
  • Request bodies are JSON. Send Content-Type: application/json.
  • Amounts are integers in the currency's smallest unit — 4280 is $42.80.
  • Timestamps are RFC 3339 in UTC, e.g. 2026-07-27T09:14:22Z.
  • Every object has a prefixed id (ch_, cus_, po_) so you always know what you are holding.
first-request.sh bash
# Create a charge in the sandbox
curl https://api.sandbox.bearmerchant.com/v1/charges \
  -u sk_test_51H8xQ2p: \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 8f14e45f-ea01-4f2b-9c39-1b7d2a6c0e11" \
  -d '{
    "amount": 4280,
    "currency": "usd",
    "payment_method": "pm_card_visa",
    "description": "Order #1042"
  }'

Core endpoints

The resources most integrations touch. Every collection endpoint supports the same pagination and filtering parameters described below.

Charges

MethodPathDescription
POST /v1/charges Create and authorise a charge
GET /v1/charges/:id Retrieve a single charge
GET /v1/charges List charges, newest first
POST /v1/charges/:id/capture Capture a previously authorised charge
POST /v1/charges/:id/refund Refund all or part of a charge

Customers and payment methods

MethodPathDescription
POST /v1/customers Create a customer
GET /v1/customers/:id Retrieve a customer
PATCH /v1/customers/:id Update a customer
DELETE /v1/customers/:id Delete a customer and its tokens
POST /v1/payment_methods Tokenise a card or bank account
POST /v1/payment_methods/:id/attach Attach a payment method to a customer

Subscriptions and payouts

MethodPathDescription
POST /v1/subscriptions Start a subscription
PATCH /v1/subscriptions/:id Change plan, quantity or billing anchor
DELETE /v1/subscriptions/:id Cancel, immediately or at period end
GET /v1/payouts List settlements to your bank account
GET /v1/balance Current available and pending balance

Disputes

MethodPathDescription
GET /v1/disputes List chargebacks and enquiries
GET /v1/disputes/:id Retrieve a dispute with its deadline
POST /v1/disputes/:id/evidence Submit representment evidence
POST /v1/disputes/:id/accept Accept liability and close the case

The charge object

Charges are the object you will handle most. A successful response looks like this:

charge.json json
{
  "id": "ch_3PkX9a2eZvKYlo2C",
  "object": "charge",
  "amount": 4280,
  "amount_refunded": 0,
  "currency": "usd",
  "status": "succeeded",
  "captured": true,
  "description": "Order #1042",
  "customer": "cus_9Fq2LmTd",
  "payment_method": {
    "id": "pm_1KdY7x",
    "brand": "visa",
    "last4": "4242",
    "exp_month": 8,
    "exp_year": 2027
  },
  "outcome": {
    "network_status": "approved_by_network",
    "risk_level": "normal",
    "risk_score": 8,
    "three_d_secure": "authenticated"
  },
  "metadata": { "order_id": "1042" },
  "created": "2026-07-27T09:14:22Z"
}

Create charge parameters

ParameterTypeRequiredDescription
amount integer Required Amount in the smallest currency unit. Must be positive.
currency string Required Three-letter ISO code, lowercase — usd, eur, gbp.
payment_method string Required A tokenised payment method id, or a customer's default when customer is set.
customer string Optional Attach the charge to an existing customer.
capture boolean Optional Defaults to true. Set false to authorise now and capture later.
three_d_secure string Optional automatic (default), any or never. Exemptions are applied where they qualify.
description string Optional Shown on your dashboard and, where supported, on the cardholder statement.
statement_descriptor string Optional Up to 22 characters. Use something the cardholder will recognise — vague descriptors drive disputes.
metadata object Optional Up to 40 key/value pairs of your own data. Returned on every read and every webhook.

Idempotency

Any POST can be retried safely by sending an Idempotency-Key header. If a request with that key has already succeeded, the original response is replayed instead of creating a second charge.

retry.sh bash
curl https://api.bearmerchant.com/v1/charges \
  -u sk_live_…: \
  -H "Idempotency-Key: 8f14e45f-ea01-4f2b-9c39-1b7d2a6c0e11" \
  -d '{ "amount": 4280, "currency": "usd", "payment_method": "pm_1KdY7x" }'

# Send the identical request again — you get the same charge back,
# not a second one, and the response carries Idempotent-Replayed: true
Keys are scoped to your account and retained for 24 hours. Generate a fresh UUID per logical operation — reusing one key for a genuinely different request returns an error rather than silently overwriting.

Pagination and filtering

List endpoints are cursor-paginated. Pass the id of the last object you saw as starting_after to fetch the next page — offsets are not used, so pages stay stable while new objects arrive.

ParameterTypeRequiredDescription
limit integer Optional Between 1 and 100. Defaults to 25.
starting_after string Optional Object id to start after. Use for the next page.
ending_before string Optional Object id to end before. Use for the previous page.
created[gte] string Optional RFC 3339 timestamp. Also accepts gt, lte, lt.
status string Optional Filter by object status, e.g. succeeded or failed.
list-response.json json
{
  "object": "list",
  "url": "/v1/charges",
  "has_more": true,
  "data": [ { "id": "ch_3PkX9a2eZvKYlo2C", /* … */ } ]
}

Errors

Errors use conventional HTTP status codes and always return a body describing what went wrong and, where the problem is fixable, which parameter caused it.

error.json json
{
  "error": {
    "type": "card_error",
    "code": "insufficient_funds",
    "message": "The card has insufficient funds to complete this charge.",
    "decline_code": "51",
    "charge": "ch_3PkX9a2eZvKYlo2C",
    "doc_url": "https://bearmerchant.com/api-reference#errors"
  }
}
StatusTypeWhat it means
400invalid_request_errorA parameter is missing or malformed. Fix the request.
401authentication_errorThe key is missing, revoked or wrong for this environment.
402card_errorThe card was declined. decline_code tells you whether a retry is worth attempting.
403permission_errorThe key is valid but lacks the scope for this endpoint.
404not_found_errorNo object with that id, or it belongs to another account.
409idempotency_errorThe idempotency key was reused with different parameters.
429rate_limit_errorToo many requests. Back off and retry — see below.
5xxapi_errorSomething failed on our side. Safe to retry with the same idempotency key.
Never branch on the human-readable message — it can change. Branch on type and code, which are stable contract.

Rate limits

Limits are applied per account, not per key, and are generous enough that normal traffic never touches them. Every response carries your current position so you can pace yourself before being throttled.

HeaderMeaning
RateLimit-LimitRequests permitted in the current window
RateLimit-RemainingRequests left in the current window
RateLimit-ResetSeconds until the window resets
Retry-AfterSent with a 429 — wait this many seconds
  • Read endpoints: 100 requests per second.
  • Write endpoints: 50 requests per second.
  • Bulk exports and reporting: 10 requests per second.
  • Retry a 429 with exponential backoff and jitter — a tight retry loop will keep you throttled.