{"openapi":"3.1.0","info":{"title":"Seeking Data Labs Sightline API","version":"2026-09","description":"Automated product audits: analysis runs, hosted reports and their findings, sharing, credits and consulting. Every answer carries the {data, meta, provenance} envelope; errors are RFC 9457 application/problem+json."},"servers":[{"url":"https://api.seekingdatalabs.com"}],"paths":{"/auth/2fa/verify":{"post":{"summary":"Answer a TOTP challenge issued by /auth/login","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}}},"/auth/login":{"post":{"summary":"Sign in with email and password (may answer a TOTP challenge)","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}}},"/auth/logout":{"post":{"summary":"End the session","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}}},"/auth/oauth/google":{"get":{"summary":"Begin Google OAuth (302 to Google)","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}}},"/auth/oauth/google/callback":{"get":{"summary":"Google OAuth return leg","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}}},"/auth/password/forgot":{"post":{"summary":"Start a password reset","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}}},"/auth/password/reset":{"post":{"summary":"Finish a password reset","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}}},"/auth/providers":{"get":{"summary":"Which sign-in providers are configured","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}}},"/auth/signup":{"post":{"summary":"Create an account (email confirmation required before sign-in)","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}}},"/auth/verify-email":{"post":{"summary":"Confirm an email address from the mailed link","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}}},"/auth/verify-email/resend":{"post":{"summary":"Resend the confirmation email","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}}},"/v1/account":{"get":{"summary":"The signed-in account: email, plan, entitlements, keys","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}}},"/v1/account/2fa":{"get":{"summary":"Second-factor status","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}}},"/v1/account/2fa/activate":{"post":{"summary":"Activate TOTP with a first code","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}}},"/v1/account/2fa/disable":{"post":{"summary":"Disable TOTP","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}}},"/v1/account/2fa/enrol":{"post":{"summary":"Begin TOTP enrolment","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}}},"/v1/account/2fa/{id}":{"post":{"summary":"/v1/account/2fa/{id}","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/account/billing/history":{"get":{"summary":"The caller's own payments and credit movements, newest first","description":"One page of the signed-in account's billing history: every movement on the prepaid credit balance (top-ups, report and subscription spends, grants, revokes, refunds) plus on-chain deposits that paid the caller's own report runs or consulting bookings directly. Strictly owner-scoped: unmatched deposits and other accounts' rows are never listed. Returned in the {data, meta, provenance} envelope with an opaque cursor; meta.next_cursor resumes after the last row returned, and meta.truncated says whether rows were dropped to fit max_response_tokens. Transaction signatures are given bare, with no explorer link.","tags":["portal"],"parameters":[{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque cursor from a previous response's meta.next_cursor."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"description":"Rows per page (1-100, default 25). Out of range is a 400."},{"name":"max_response_tokens","in":"query","required":false,"schema":{"type":"integer","minimum":500,"maximum":16000,"default":4000},"description":"Token budget for the response; whole tail rows are dropped to fit."}],"responses":{"200":{"description":"One page of history in the {data, meta, provenance} envelope","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"ledger:<n> or payment:<n>"},"kind":{"type":"string","enum":["ledger","payment"]},"at":{"type":"string","format":"date-time"},"reason":{"type":"string","description":"Credit ledger reason, or report_payment / booking_payment for a direct deposit."},"direction":{"type":"string","enum":["credit","debit","payment"]},"amount_atomic":{"type":"integer","description":"Money moved, positive, USDC atomic units (1000000 = $1)."},"balance_delta_atomic":{"type":"integer","description":"Signed effect on the credit balance; 0 for a direct payment."},"ref":{"type":["string","null"],"description":"The caller's own order id (run, booking, subscription), when there is one."},"tx_signature":{"type":["string","null"],"description":"On-chain transaction signature, when the money moved on chain."}}}},"meta":{"type":"object"},"provenance":{"type":"object"}}}}}},"400":{"description":"Invalid limit, max_response_tokens or cursor (application/problem+json)"},"401":{"description":"No valid session"}}}},"/v1/account/nickname":{"put":{"summary":"Set the public nickname","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}}},"/v1/agent/whoami":{"get":{"summary":"Agent-auth introspection","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}}},"/v1/analysis/auto-rescan":{"post":{"summary":"Toggle the weekly auto re-scan for a domain","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}}},"/v1/analysis/credentials":{"delete":{"summary":"Sign-in credentials for authenticated audits (owner-gated)","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}},"get":{"summary":"Sign-in credentials for authenticated audits (owner-gated)","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}},"post":{"summary":"Sign-in credentials for authenticated audits (owner-gated)","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}}},"/v1/analysis/dns-provider":{"get":{"summary":"Detect the DNS provider for setup help","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}}},"/v1/analysis/domains":{"get":{"summary":"Domains on the account / add one for verification","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}},"post":{"summary":"Domains on the account / add one for verification","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}}},"/v1/analysis/entitlement":{"get":{"summary":"What a run of each tier costs this account now","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}}},"/v1/analysis/report/{id}":{"get":{"summary":"A finished report body (owner-gated)","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/analysis/report/{id}/pdf":{"get":{"summary":"The report PDF (owner-gated)","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/analysis/report/{id}/share":{"delete":{"summary":"Mint or revoke the share link; set who it works for","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]},"post":{"summary":"Mint or revoke the share link; set who it works for","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/analysis/report/{id}/trace":{"get":{"summary":"Live pipeline trace while a run executes","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/analysis/reports":{"get":{"summary":"Runs and their status for a domain","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}}},"/v1/analysis/run":{"post":{"summary":"Commission an analysis run (charges credit or quotes USDC)","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}}},"/v1/analysis/shared/{id}":{"get":{"summary":"A shared report body (token is the credential)","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/analysis/shared/{id}/pdf":{"get":{"summary":"A shared report PDF","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/analysis/verify":{"get":{"summary":"Check DNS TXT ownership verification","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}}},"/v1/audit/authorization":{"get":{"summary":"The active-testing authorization for a verified domain, if any (§7/ADR 0012)","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}}},"/v1/audit/authorization/revoke":{"post":{"summary":"Revoke an active-testing authorization (§7)","tags":["portal"],"responses":{"200":{"description":"Revoked"},"401":{"description":"No valid session"},"404":{"description":"No active authorization"}}}},"/v1/audit/authorize":{"post":{"summary":"Authorize active security testing of a verified domain: the ADR 0012 ownership attestation (section 7)","tags":["portal"],"responses":{"201":{"description":"Authorized"},"400":{"description":"Domain not verified or no attestation"},"401":{"description":"No valid session"}}}},"/v1/audit/subscribe":{"post":{"summary":"Buy a monthly audit subscription (sightline|sightline_secure|sightline_review) from credit (§4)","tags":["portal"],"responses":{"200":{"description":"Subscribed"},"401":{"description":"No valid session"},"402":{"description":"Insufficient credit"}}}},"/v1/audit/subscription":{"get":{"summary":"The caller's current audit subscription tier, grant and expiry (§4)","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}}},"/v1/billing/account":{"get":{"summary":"Deposit address and account memo for USDC top-ups","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}},"deprecated":true,"description":"Deprecated. Legacy subscription deposit rail whose memo is the bare account id; subscription tiers are retired. To add credit use GET /v1/credits (its topup block carries the correct top-<account-id> memo)."}},"/v1/consulting/bookings":{"get":{"summary":"Create or list consulting bookings","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}},"post":{"summary":"Create or list consulting bookings","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}}},"/v1/consulting/slots":{"get":{"summary":"Booked consulting slots in a window","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}}},"/v1/credits":{"get":{"summary":"Prepaid credit balance and paginated transaction ledger","description":"Returns the account's USDC credit balance and one page of the append-only transaction ledger (top-ups, report charges, refunds), newest first. Cursor-paginated: pass the previous response's next_before as before to fetch the following page. balance_atomic is the server's running total over the WHOLE ledger, not the sum of the returned page. The topup block carries the deposit address and the exact top-<account-id> memo that adds credit (a bare account id is a different rail and does not add credit).","tags":["portal"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"description":"Ledger rows per page (1-100, default 25)."},{"name":"before","in":"query","required":false,"schema":{"type":"integer","minimum":1},"description":"Pagination cursor: return entries with id < before. Use the previous page's next_before."}],"responses":{"200":{"description":"Balance plus one page of ledger entries","content":{"application/json":{"schema":{"type":"object","properties":{"balance_atomic":{"type":"integer","description":"USDC 6-decimal atomic units; running total over the whole ledger."},"balance_usd":{"type":"number","description":"Display convenience; balance_atomic is authoritative."},"entries":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","description":"Monotonic ledger id; also the pagination cursor."},"created_at":{"type":"string","format":"date-time"},"delta_atomic":{"type":"integer","description":"Signed movement in atomic USDC; negative is a debit."},"direction":{"type":"string","enum":["credit","debit"]},"reason":{"type":"string","enum":["report","topup_usdc","topup_manual","admin_grant","admin_revoke","refund"]},"ref":{"type":["string","null"],"description":"Free-form reference (report id, tx signature)."},"actor":{"type":"string"}}}},"next_before":{"type":["integer","null"],"description":"Cursor for the next page, or null on the last page."},"topup":{"type":"object","properties":{"deposit_address":{"type":"string"},"memo":{"type":"string","description":"Exact top-<account-id> memo that credits this account."},"asset":{"type":"string"},"network":{"type":"string"}}}}}}}},"401":{"description":"No valid session"}}}},"/v1/keys":{"post":{"summary":"Create an API key","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}}}},"/v1/keys/{id}/revoke":{"post":{"summary":"Revoke an API key","tags":["portal"],"responses":{"200":{"description":"OK"},"401":{"description":"No valid session"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/requests":{"post":{"summary":"Request a security assessment (kind pentest), a discussion of it, or consultancy (records intent; does not run anything)","description":"Records a service request onto the operator review board and returns the running count for this (account, domain, kind). This is the ONLY way to ask for a security assessment (a penetration test only with written authorisation for active testing; the kind value stays `pentest`): it does NOT trigger, queue, or execute any scan. A human operator reviews the request and the assessment, if agreed, is dispatched internally after an offline authorization/contract. Repeated identical requests are deduplicated and increment count rather than creating duplicates. Requires a valid session.","tags":["portal"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["kind"],"properties":{"kind":{"type":"string","enum":["pentest","pentest_discussion","consultancy"]},"domain":{"type":"string","description":"Bare hostname the request concerns; omitted/empty for consultancy."},"detail":{"type":"string","description":"Optional free-text note or topic."}}}}}},"responses":{"200":{"description":"Request recorded","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"count":{"type":"integer","description":"How many times this (account, domain, kind) has been requested."}}}}}},"400":{"description":"Unknown kind or malformed body"},"401":{"description":"No valid session"}}}}}}