Authentication
Start with a free account at /app/signup.
Once signed in you can mint an API key with a session-authed
POST /v1/keys; the plaintext key is returned once, on
creation, and never shown again.
Every request is authenticated one of two ways: the browser session
cookie (for calls made from the signed-in portal), or a
Bearer API key in the Authorization header
(for calls made by your own code or an agent). The examples below use
a Bearer key.
curl -sS -X POST https://api.seekingdatalabs.com/v1/keys \
--cookie "$SEEKINGDATA_SESSION" \
-H "Content-Type: application/json" \
-d '{"name":"my-agent"}'
The reporting flow
A report goes through three steps: commission a run, poll it until it
is ready, then fetch the result. Runs are asynchronous: the
run call returns immediately with a report id and a
status, and the report fills in as the fleet works.
1. Run a report
POST /v1/analysis/run commissions a run. It requires a
verified domain you own and available credit; each run is charged from
your balance (or, if the balance is short, the response returns a USDC
deposit address and a memo instead). The report_type query
parameter selects the product: analyzer for the website
audit (the default) or asvs for the OWASP ASVS security
posture report. Any other value folds to analyzer. The
asvs report needs an active security subscription.
curl -sS -X POST \
"https://api.seekingdatalabs.com/v1/analysis/run?domain=example.com&report_type=analyzer" \
-H "Authorization: Bearer $SEEKINGDATA_KEY"
The response carries a report_id and a
status. When the balance covers the run it is
queued straight away; when it does not, the run is held
awaiting_payment and the response returns the deposit
address and the memo to send USDC to.
2. Poll until ready
GET /v1/analysis/reports lists your runs. Fetch a single
run with GET /v1/analysis/report/{id} and poll it
until its status is ready.
The listing answers with the current report for each domain. Once a
newer report replaces an older one, the older is marked superseded
and left out of the list; pass ?archived=1 to get the
whole history back, with an archived_at on every
superseded run. Superseded reports keep resolving by id and by share
link, so anything you have already handed out still opens.
curl -sS "https://api.seekingdatalabs.com/v1/analysis/reports" \
-H "Authorization: Bearer $SEEKINGDATA_KEY"
curl -sS "https://api.seekingdatalabs.com/v1/analysis/report/rep-0a1b2c3d4e5f" \
-H "Authorization: Bearer $SEEKINGDATA_KEY"
3. Fetch the report
Once a run is ready, three views are available:
-
GET /v1/analysis/report/{id}— the full report envelope. -
GET /v1/analysis/report/{id}/findings— the structured findings for the run. -
GET /v1/analysis/report/{id}/pdf— the report as a PDF.
curl -sS "https://api.seekingdatalabs.com/v1/analysis/report/rep-0a1b2c3d4e5f/findings" \
-H "Authorization: Bearer $SEEKINGDATA_KEY"
curl -sS "https://api.seekingdatalabs.com/v1/analysis/report/rep-0a1b2c3d4e5f/pdf" \
-H "Authorization: Bearer $SEEKINGDATA_KEY" \
-o report.pdf
Sharing a report
POST /v1/analysis/report/{id}/share mints an
unguessable share token; the matching
DELETE revokes it. Anyone holding the token can then read
the report with GET /v1/analysis/shared/{token},
which is public and needs no authentication. The token is the whole
credential, so share it deliberately.
curl -sS -X POST \
"https://api.seekingdatalabs.com/v1/analysis/report/rep-0a1b2c3d4e5f/share" \
-H "Authorization: Bearer $SEEKINGDATA_KEY"
# The returned token reads publicly, no key:
curl -sS "https://api.seekingdatalabs.com/v1/analysis/shared/$SHARE_TOKEN"
Credit balance and transactions
GET /v1/credits returns your balance and the recent
movements that built it. The balance is the running sum of an
append-only ledger, so the numbers always reconcile. Key fields:
-
balance_atomic— the running total over the whole ledger, in atomic USDC units (millionths).balance_usdis the same figure in dollars. -
entries[]— the recent movements, each with anid,created_at, a signeddelta_atomic, adirection(creditordebit), areason, aref, and anactor. -
next_before— the pagination cursor. Pass it back asbefore=to fetch the next page; it isnullon the last page. -
topup— how to add credit: a deposit address and the exacttop-<account-id>memo that credits your account (USDC on Solana). The memo is served complete; send it exactly, or the deposit cannot be matched to your account.
curl -sS "https://api.seekingdatalabs.com/v1/credits?limit=25" \
-H "Authorization: Bearer $SEEKINGDATA_KEY"
# Next page: pass the previous response's next_before
curl -sS "https://api.seekingdatalabs.com/v1/credits?limit=25&before=1024" \
-H "Authorization: Bearer $SEEKINGDATA_KEY"
Reports and priced data calls are paid from this balance by default; a call your plan already covers stays free. Credit lands once a top-up transfer confirms on chain, not the instant it is sent.
Pentest and consultancy are not self-serve
There is no API that runs a penetration test. A pentest is a scoped, authorized engagement: it runs only after an offline authorization and contract, and is dispatched internally by an operator. Nothing you can call here starts one.
What you can do through the API is record intent. A
POST /v1/requests files a request for a human operator to
review; it changes nothing about your account and starts no work. The
body takes a kind of
pentest, pentest_discussion, or
consultancy, a domain (required for the
pentest kinds; omitted for consultancy), and an optional free-text
detail.
curl -sS -X POST https://api.seekingdatalabs.com/v1/requests \
-H "Authorization: Bearer $SEEKINGDATA_KEY" \
-H "Content-Type: application/json" \
-d '{"kind":"pentest","domain":"example.com","detail":"Pre-launch review of the checkout flow."}'
A repeat request for the same domain and kind stacks rather than duplicating. An operator picks it up from there.