RedSwitches API Private beta Reference
Menu

SDKs

Official clients for TypeScript, Python and Go: install, set up, and how they handle idempotency, retries and errors. All three behave the same way.

Install

LanguagePackageNeeds
TypeScript / JavaScript@redswitches/apiNode 20+ or any runtime with fetch. No other dependencies.
PythonredswitchesPython 3.9+. One dependency: httpx. Sync Client and async AsyncClient.
Gogithub.com/redswitches/redswitches-goGo 1.23+. Standard library only.

Until the packages are published, install from a checkout of the toolkit repository:

npm install ./sdk/typescript          # TypeScript: @redswitches/api
pip install ./sdk/python              # Python: redswitches
# Go: point a replace directive in your go.mod at the sdk/go folder

Set up a client

Each client reads the key from REDSWITCHES_API_KEY when you do not pass one. The key is sent only in the Authorization header and never appears in logs, errors or printed objects.

export REDSWITCHES_API_KEY='rsw_live_XXXX…'
import { RedSwitches } from "@redswitches/api";

const rs = new RedSwitches(); // or new RedSwitches({ apiKey, timeoutMs: 30000, maxRetries: 3 })
const key = await rs.auth.verify();
from redswitches import Client

with Client() as client:  # or Client(api_key="rsw_live_XXXX…", max_retries=3)
    key = client.auth.verify()
client := redswitches.NewClient("") // "" reads REDSWITCHES_API_KEY
key, err := client.Auth.Verify(ctx)

Lists can be read page by page (list with limit and cursor) or walked to the end (iterate / all in TypeScript and Python, All in Go), which follows next_cursor for you.

Idempotency

  • Every POST and DELETE carries an Idempotency-Key. Pass your own (idempotencyKey, idempotency_key=, RequestOptions{IdempotencyKey}), or the SDK makes a fresh one for the call.
  • Every retry of that call reuses the same key, so a retried order or reboot happens once.
  • An order dry run (dryRun: true, dry_run=True, OrderOptions{DryRun: true}) sends no Idempotency-Key: it changes nothing.
  • A real order needs expected_total from a dry run; the SDKs refuse to send one without it.
  • If a write fails with a network error, call it again with the same key to get the original outcome. Python errors carry the key that was sent (err.idempotency_key).

See Idempotency and retries for what the API returns on a repeat.

Retries

The SDKs retry only when it is safe and the API asks for it:

AnswerRetried?
Network error or timeoutYes, with the same Idempotency-Key. Never for GET /actions/{id}/credentials.
429 rate_limitedYes, after Retry-After.
503 unavailableYes, after Retry-After, else 2, 4, 8 seconds. Never for GET /actions/{id}/credentials.
409 in_progressYes, after Retry-After / details.retry_after, with the same key.
429 action_limitNo. A ceiling of the account; it will not pass in seconds.
403 cooling_offNo. Ordering opens later; details.retry_after says when.
Anything else (500, 409 server_busy, 409 price_changed, 409 order_under_review, …)No.

At most 3 retries by default. A requested wait longer than about a minute is returned as the error instead of slept.

GET /actions/{id}/credentials is never retried after a network error or a 5xx answer: the lost answer may already have used up the one read. It is retried only after 429 rate_limited, when nothing was read. See Rescue and one-time credentials.

Errors

Every failure is one error type with the API's code, status, message, details and request id. Write your code against code; quote the request id to support.

import { RedSwitchesError } from "@redswitches/api";

try {
  await rs.orders.create({ ...body, expected_total: quote.total });
} catch (e) {
  if (e instanceof RedSwitchesError && e.code === "price_changed") console.log("now", e.details.total);
  else throw e;
}
from redswitches import RedSwitchesError

try:
    client.orders.create(**body, expected_total=quote.total)
except RedSwitchesError as err:
    if err.code != "price_changed":
        raise
    print("now", err.details)
_, err := client.Orders.Create(ctx, req, nil)
if redswitches.ErrorCode(err) == "price_changed" {
	var apiErr *redswitches.Error
	if errors.As(err, &apiErr) {
		fmt.Println("now", apiErr.Details.Total)
	}
}

Client-side failures have their own codes in TypeScript (network_error, timeout, invalid_argument, …), and their own exception classes in Python (APIConnectionError, …). Go returns the transport error itself.

All error codes are on Rate limits and errors.

Also built on the SDKs