Send over HTTPS

POST a base64 encoded, already-signed Solana transaction to https://send.swqos.com/v1/transactions. The response is a receipt naming the signature, whether it was a duplicate, what you were charged, and your remaining balance.


The request#

POST https://send.swqos.com/v1/transactions with Content-Type: application/json. Send your bearer token for balance payment, or omit it when the signed transaction contains the exact payment published by/v1/pricing. Bodies are capped at 8 KiB.

FieldTypeMeaning
transactionstring, requiredBase64 of the serialized signed transaction. Legacy or versioned. At most 1232 bytes before encoding.
We forward the bytes unchanged. We do not re-sign, reorder, add a tip instruction, adjust a priority fee, or touch the transaction in any way. Whatever you serialize is what reaches the leader.

The receipt#

A successful submission returns HTTP 200 and this object.

FieldTypeMeaning
signaturestringThe transaction signature, extracted from the bytes you submitted. It will always match what you signed.
acceptedbooleanTrue when the submission was forwarded and acknowledged upstream, or matched a recent duplicate.
duplicatebooleanTrue when this signature was already accepted within the last 90 seconds. Not forwarded again and not charged.
charged_lamportsintegerThe amount reserved from balance. It settles on landing and is fully refunded after proven non-landing. Zero for direct payment or duplicates.
balance_remaining_lamportsintegerYour prepaid balance after this submission.
payment_modestringbalance when a prepaid amount was reserved; transaction when the signed transaction carries the exact service payment.

Anything other than HTTP 200 returns an error object with a code and a message. Every code is documented in errors, along with what causes it and how to fix it.

A complete example#

TypeScript
1const res = await fetch("https://send.swqos.com/v1/transactions", {
2 method: "POST",
3 headers: {
4 Authorization: `Bearer ${process.env.SWQOS_API_KEY}`,
5 "Content-Type": "application/json",
6 },
7 body: JSON.stringify({
8 transaction: Buffer.from(tx.serialize()).toString("base64"),
9 }),
10});
11
12const { signature, charged_lamports } = await res.json();

Duplicates#

We deduplicate on your account plus the transaction signature for 90 seconds. Resubmitting the same signed bytes inside that window returns accepted: true, duplicate: true and charged_lamports: 0. Nothing is forwarded a second time and you are not charged again.

Racing submissions

If an identical submission is still in flight, the second one returns 409 SUBMISSION_IN_PROGRESS rather than being queued. Wait for the first to return instead of retrying immediately.

After the 90 second window the same bytes can be forwarded again. By then the blockhash is usually expired; its balance reservation will be refunded after non-landing is proven, but you should build a fresh transaction instead.

Reading the price#

The public default price is available without authentication. It is the global default, not your account’s effective price, so use /v1/account when the distinction matters.

pricing
1curl -sS https://send.swqos.com/v1/pricing
2
3# {
4# "default_tip_lamports": 100000,
5# "default_markup_bps": 5000,
6# "default_total_lamports": 150000,
7# "billing_event": "landed_transaction",
8# "refunded_when_not_landed": true,
9# "in_transaction_payment_enabled": true,
10# "in_transaction_payment_recipient": "<service payment wallet>",
11# "in_transaction_payment_lamports": 150000
12# }

When to use HTTPS#

HTTPS is the right choice when you are adding swqos.com to an existing service, when your runtime makes raw QUIC awkward, or when a few milliseconds do not decide the outcome. It is a plain JSON POST and it works everywhere.

If latency is the reason you are here, use QUIC instead. Holding one connection open removes a TLS handshake and a TCP round trip from every single send.