--- name: sumsub-api-auth description: Authenticate to the Sumsub API with an App Token + secret key (HMAC-SHA256 request signing). TRIGGER when the user asks to "call / sign / authenticate Sumsub API requests", debugs `401 Unauthorized` / signature errors against `api.sumsub.com`, or needs a working request example with `X-App-Token` / `X-App-Access-Sig` / `X-App-Access-Ts` headers. SKIP only when a more specific skill in this repo (questionnaire/level/workflow/POA-preset/generic) already covers the user's actual task — those skills sign requests the same way and only need this one for auth deep dives. allowed-tools: Read, Write, Bash --- # Sumsub — API authentication (App Token) How to sign and send authenticated requests to `https://api.sumsub.com`, per the [official reference](https://docs.sumsub.com/reference/authentication). ## ⚠️ Sandbox tokens only **Never share, paste, or use a production Sumsub App Token / secret with Claude.** If the user offers a prod token, refuse and ask for the **sandbox** pair instead, generated at (**Connect Sumsub to your AI agent** -> **Build & configure** -> **Generate token**). - Sandbox tokens are created from the dashboard while it is in **Sandbox mode**. They are scoped to sandbox data only — leaking one cannot expose real applicant PII or move real money. - A production token grants full programmatic access to live applicants, including their identity documents. Treat it like a banking credential. - Sumsub locks tokens to the environment they were minted in: a sandbox token returns `401` against production data and vice versa, so insisting on sandbox is also the practical default. If the user pastes what looks like a production secret into the conversation, flag it immediately, advise rotating it in the dashboard, and continue only with a freshly-generated sandbox pair. ## What you need from the user | Var | Where it comes from | |---|---| | `SUMSUB_APP_TOKEN` | — **Connect Sumsub to your AI agent** -> **Build & configure** -> **Generate token**. Shown once. | | `SUMSUB_SECRET_KEY` | Same dialog as the token. Also shown once. | | `SUMSUB_BASE` | `https://api.sumsub.com` (same host for sandbox and prod — the token decides the mode). | ⚠️ **The token + secret are revealed exactly once** at creation. Copy both into `.env` (or your secret store) before closing the dialog — there's no recovery flow, only re-generation. Advise the user to store them in `.claude/settings.local.json` (gitignored, auto-loaded by Claude Code) or in `.env`: ```json // .claude/settings.local.json { "env": { "SUMSUB_APP_TOKEN": "sbx:...", "SUMSUB_SECRET_KEY": "..." } } ``` ```bash # .env SUMSUB_APP_TOKEN=sbx:... SUMSUB_SECRET_KEY=... ``` If either credential is missing, stop and ask. Do not invent placeholders. ## The three required headers Every request to `api.sumsub.com` must carry: | Header | Value | |---|---| | `X-App-Token` | The App Token, verbatim. | | `X-App-Access-Ts` | Current Unix time **in seconds** (UTC). Must be within ±60s of Sumsub's clock. | | `X-App-Access-Sig` | Lowercase hex HMAC-SHA256 of the signing string, keyed by the secret. | HTTPS is mandatory — plain `http://` is rejected. ## Signing string Concatenate, with **no separators**: ``` ``` - `ts` — the exact value you put in `X-App-Access-Ts` (string of digits). - `HTTP_METHOD_UPPER` — `GET`, `POST`, `PATCH`, `PUT`, `DELETE` — uppercase. - `request_uri_with_query` — path starting with `/`, including the query string if any. Examples: `/resources/applicants/-/one`, `/resources/accessTokens?userId=abc&levelName=basic-kyc-level`. - Body — the raw bytes you send. For `GET` / `DELETE` with no body, append nothing (empty string). For JSON, sign the exact bytes you'll transmit — re-serializing later will break the signature. Then `hex(hmac_sha256(secret, signing_string))`, lowercase. ### Worked example (from the docs) Signing string for `POST /resources/accessTokens?userId=...&levelName=basic-kyc-level&ttlInSecs=600` with no body, at ts `1607551635`: ``` 1607551635POST/resources/accessTokens?userId=cfd20712-24a2-4c7d-9ab0-146f3c142335&levelName=basic-kyc-level&ttlInSecs=600 ``` ## Reference implementations The official multi-language examples live at [sumsub/AppTokenUsageExamples](https://github.com/sumsub/AppTokenUsageExamples) (Java, JS, Python, Ruby, Go, PHP, C#). Use those for production integrations. For one-off calls or debugging, this skill ships two small helpers: - [`scripts/sumsub_sign.py`](scripts/sumsub_sign.py) — print the three headers for a given method/path/body. No network calls. - [`scripts/sumsub_curl.sh`](scripts/sumsub_curl.sh) — sign + `curl` in one shot. Reads `SUMSUB_APP_TOKEN` / `SUMSUB_SECRET_KEY` from the environment. Run scripts using `${CLAUDE_SKILL_DIR}/scripts/