soldout/ akamai

API reference

Two endpoints. POST /v3 returns sensor data for the _abck cookie, POST /sbsd returns the SBSD body. Device selection, script analysis and challenge solving all happen on our side.

The request format is Hyper's, so an existing hyper_sdk integration works by changing the base URL and nothing else.

Base URL

Requests are JSON over HTTPS. There is no version in the path.

base url
https://sold-out.dev
routes
# sensor data
POST /v3
POST /v2/sensor      # same handler, older path

# sbsd body
POST /sbsd

Authentication

Every solve call carries an API key. Three headers are accepted so a client written against another provider does not have to change how it builds requests. All three resolve the same credential.

x-api-keystring

The default.

x-keystring

Alternative spelling, for clients that already send it.

Authorizationstring

Bearer token form.

Keys are created in the dashboard and stay visible in your key list, so you can copy one again at any time. If a key is compromised, delete it and create a new one.

request headers
x-api-key: ak_live_7f3c…

# or
x-key: ak_live_7f3c…
Authorization: Bearer ak_live_7f3c…

SDKs

Official client libraries for Go, JavaScript and Python wrap authentication and the request format, so you call a method instead of building JSON by hand. They speak the same Hyper format the raw API does — nothing below changes.

Find them, with install and usage instructions, on our GitHub: github.com/sold-out-dev.

Prefer HTTP? Every endpoint on this page works directly with any HTTP client — the SDKs are a convenience, not a requirement.

libraries
# Go
go get github.com/sold-out-dev/sold-universal-sdk-go

# JavaScript / TypeScript
npm install sold-universal-sdk-js

# Python
pip install sold-universal-sdk
all repositories
https://github.com/orgs/sold-out-dev/repositories
POST/v3

Sensor data

Returns the payload to post to the sensor endpoint, which turns your _abck cookie valid. Also reachable at /v2/sensor, the same handler under the path older Hyper clients use.

Body parameters

userAgentstringrequired

Desktop Google Chrome. The major version decides which fingerprint pool is drawn from.

pageUrlstringrequired

The page the sensor is posted from.

abckstringrequired

Current _abck cookie value.

bmszstringrequired

Current bm_sz cookie value. It also pins the session to one fingerprint, so a session keeps the same device throughout.

scriptstringfirst call

The sensor script body. Send it once per session, then send context instead. null is accepted and means the same as omitting it.

contextstring

Opaque token from the previous response. Carries the script analysis forward so repeat calls skip the expensive part. null is accepted and means the same as omitting it.

ipstring

The address the sensor will be posted from. Used for geo-consistent values.

acceptLanguagestring

Matches the header you will send.

scriptUrlstring

Path the script was served from.

iterationinteger

0-based index of this sensor within the session. Defaults to 0.

Response

payloadstring

Post this to the sensor endpoint as-is.

contextstring

Keep it and send it back on the next call in the same session.

request
curl https://sold-out.dev/v3 \
  -H "x-api-key: $SOLDOUT_KEY" \
  -H "content-type: application/json" \
  -d '{
    "pageUrl": "https://target.com/",
    "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64…",
    "abck": "<_abck cookie>",
    "bmsz": "<bm_sz cookie>",
    "script": "<sensor script>",
    "ip": "1.2.3.4"
  }'
200 response
{
  "payload": "3;0;1;0;3490105;Li9UX…",
  "context": "bSQ0lf…"
}
POST/sbsd

SBSD body

The full SBSD body, derived from the script and the bm_so cookie. One device for the whole session, not a fresh fingerprint per request.

Body parameters

uuidstringrequired

The UUID from the SBSD script. Without it there is nothing to encrypt against.

userAgentstringrequired

Desktop Google Chrome, same rule as /v3.

pageUrlstringrequired

The page the body is posted from.

ostringrequired

The bm_so cookie value.

scriptstringfirst call

The SBSD script body.

contextstring

Opaque token from the previous response, same role as on /v3.

ipstring

The address the body will be posted from.

acceptLanguagestring

Matches the header you will send.

scriptUrlstring

Path the script was served from.

indexinteger

0-based index of this body within the session. Defaults to 0.

Response

bodystring

The SBSD body to post.

payloadstring

The same string as body. The Hyper SDK reads this key and older clients read body, so both are returned and neither has to change.

contextstring

Send back on the next call in the same session.

request
curl https://sold-out.dev/sbsd \
  -H "x-api-key: $SOLDOUT_KEY" \
  -H "content-type: application/json" \
  -d '{
    "uuid": "9f2c1b7e-…",
    "pageUrl": "https://target.com/",
    "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64…",
    "o": "<bm_so cookie>",
    "script": "<sbsd script>",
    "ip": "1.2.3.4"
  }'
200 response
{
  "body": "eyJ6IjoiN…",
  "payload": "eyJ6IjoiN…",
  "context": "bSQ0lf…"
}
POST/pixel

Pixel body

The Akamai pixel challenge body. Give it the two values parsed from the page and the pixel script; you get back the form body to POST to the pixel_ endpoint.

Body parameters

userAgentstringrequired

Desktop Google Chrome, same rule as /v3.

htmlVarnumberrequired

The bazadebezolkohpepadr value from the page HTML.

scriptVarstringrequired

The dynamic value from the pixel script (the g=_[N] string).

ipstring

The egress IP of the request that will carry the result.

acceptLanguagestring

The Accept-Language header you send.

request
curl https://sold-out.dev/pixel \
  -H "x-api-key: $SOLDOUT_KEY" \
  -H "content-type: application/json" \
  -d '{
    "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64…",
    "htmlVar": 32,
    "scriptVar": "94621f30b57f5db88ca303259e1882fe",
    "ip": "1.2.3.4"
  }'
200 response
{
  "payload": "ap=true&bt=%7B…&t=…&u=…"
}

Sessions

A session is one browser as far as Akamai is concerned. Two things keep it coherent.

bm_sz pins the fingerprint. The same cookie draws the same device from the pool for the life of the session, so the screen, the GPU and the plugin list do not change underneath.

context carries the script analysis. Send script on the first call, keep the context that comes back, and send it instead of the script from then on. The expensive work then happens once per session rather than once per request.

one session, three calls
# 1. first sensor, send the script
POST /v3  { …, "script": "<568 KB>" }
       →  { "payload": …, "context": "bSQ0lf…" }

# 2. and after, send the context instead
POST /v3  { …, "context": "bSQ0lf…", "iteration": 1 }
       →  { "payload": …, "context": "bSQ0lf…" }

# 3. same bm_sz throughout means the same device
POST /v3  { …, "context": "bSQ0lf…", "iteration": 2 }

Errors

Every failure is a JSON object with an error string that says what was wrong with the request. Server-side faults are the one exception: they answer internal error, because the detail is about our internals and belongs in our logs, not in your client.

400bad request

Malformed JSON, a missing required field, or a user agent we do not support. Anything that is not desktop Chrome is refused, and so is a Chrome major we hold no fingerprints for. Never billed.

401unauthorized

No key presented.

402payment required

Balance is at zero. Nothing queues and nothing accrues, so the account cannot go into debt.

403forbidden

Key is unknown, revoked or expired.

502bad gateway

No solver could take the request, or the solver failed on it. The reason is in our logs, not in the response. Retry, and open a ticket if it persists. Never billed.

504timeout

No worker answered within 120 seconds. Retry. Never billed.

Only a 200 is charged. Failures are still recorded so you can see your own error rate in the dashboard, at a cost of zero. Request bodies are capped at 8 MB, which a sensor script fits into comfortably.

error shape
400 Bad Request
{ "error": "userAgent is required" }

402 Payment Required
{ "error": "insufficient balance, top up to keep solving" }

504 Gateway Timeout
{ "error": "no worker answered within 120s" }

User agents

The userAgent you send must be one we hold fingerprints for. Only desktop Chrome on Windows is supported, majors 149–151. Anything else is a 400, never billed.

Send the string exactly as listed — same casing and spacing.

supported user agents
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/150.0.0.0 Safari/537.36
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/151.0.0.0 Safari/537.36

Start with €2 and a key.

Prepaid, per request, stops at zero. No card on file, no minimum, no call required. That one is only for unlimited.

Create account