Agent Supply Trust
API reference

Agent Supply Trust API

Evaluate packages, containers, MCP servers, agent skills and plugins for provenance, permissions and runtime risk.

Quickstart

Three calls: ask for a key, claim it from your inbox, then use it. No account, no dashboard, no card.

1. Ask for a key

curl -X POST https://agentsupplytrust-api.com/v1/keys \
  -H 'content-type: application/json' \
  -d '{"email":"you@example.com","source":{"source":"web","medium":"docs"}}'

Answers 202 Accepted and emails a one-time claim token to that address. No key is returned by this call. Proving you control the mailbox is what stops anyone who can guess your address from minting a key on your account and spending your allowance. The token is good for 15 minutes; ask again if it lapses.

2. Claim it

curl -X POST https://agentsupplytrust-api.com/v1/keys/claim \
  -H 'content-type: application/json' \
  -d '{"token":"PASTE_THE_TOKEN_FROM_THE_EMAIL"}'

This response carries the key, and it is shown once — only a peppered hash is stored, so it cannot be read back later; if you lose it, rotate. Free tier: 100 component scans/month.

3. Call the API

curl -X POST https://agentsupplytrust-api.com/v1/scans \
  -H "Authorization: Bearer $KEY" \
  -H 'content-type: application/json' \
  -d '{"components":[{"kind":"mcp_server","name":"acme-mcp","version":"1.4.0"}]}'

Or skip the terminal: every endpoint below has a Try it panel that sends the real request from this page. Start at the playground.

Authentication

Authorization: Bearer sp_live_…

x-api-key is also accepted. Keys are scoped to this API — a key issued for another product returns invalid_api_key, identical to an unknown key, so the API will not confirm a key is valid elsewhere. Never put a key in browser JavaScript; authenticated endpoints deliberately do not support CORS.

Playground

Every endpoint below carries a Try it panel, prefilled with a working request. Edit it, press Send, and read what this API actually answered — status, timing, requestId and body, unedited. Requests go straight from your browser to https://agentsupplytrust-api.com; nothing is proxied through this page and no request is recorded here.

Your API key Not set

What happens to this key. It is a live credential, and it is treated as one. It is held in this page's memory for as long as the tab is open and nowhere else — not localStorage, not sessionStorage, not a cookie, not the URL, not a query string. It is never logged, and never sent to the server that serves this page. The only place it goes is the Authorization: Bearer header of requests you send to https://agentsupplytrust-api.com. Reloading or closing the tab discards it; Clear discards it now. Copied curl commands carry $KEY, never the key itself. On a shared machine, clear it when you are done.

What a call costs. Every panel says so above its Send button, taken from the same contract as the rest of this page. No key required is a public endpoint — no key, no quota, no charge. Free — no quota needs your key but reserves nothing. Billable runs against your real account and reserves the stated quota from your plan before it runs, exactly as it would from your own code. Quota: no fixed cost also runs against your real account, but the contract states no fixed amount: endpoints whose work scales with the payload reserve an amount derived from what you send, so try a small request first.

No key yet? Open the Try it panel on POST /v1/keys, put in your email and press Send. That call answers 202 and emails you a claim token; paste the token into the Try it panel on POST /v1/keys/claim and send that. The claim response is the one that carries the key, and it comes back with a button that loads it straight into this field.

Agent Supply Trust endpoints

What this API does. Everything below is specific to this product.

POST/v1/scans

Scan one component

API key requiredBillable — 1 unit or more

Analyses provenance, requested permissions and instruction surfaces. Static only — nothing is installed or executed.

Try itPOST /v1/scansBillable — 1 unit or more

Runs against your real account. The contract states no fixed quota cost, so one unit is reserved before the call runs — and an endpoint whose work scales with what you send can bill more than that. Read the description above, and start with a small request.

Using the API key from the playground key fieldno key set yet. It is sent only in the Authorization: Bearer header, only to https://agentsupplytrust-api.com.

Ready

Request body

FieldTypeNotes
kind"npm_package" | "pypi_package" | "container_image" | "mcp_server" | "agent_skill" | "plugin"required
namestringrequired
versionstringrequired
provenanceobjectoptional
permissionsstring[]optional
instructionsstring[]optionalFree-text surfaces — MCP tool descriptions, SKILL.md. Scanned for injection and exfiltration markers, which is where most scanners do not look.

Example request

{
  "kind": "mcp_server",
  "name": "acme-mcp",
  "version": "2.1.0",
  "provenance": {
    "signed": true,
    "publisherVerified": true,
    "sourceRepo": "https://github.com/acme/mcp"
  },
  "permissions": [
    "tool.invoke"
  ]
}

curl

curl -X POST https://agentsupplytrust-api.com/v1/scans \
  -H "Authorization: Bearer $KEY" \
  -H 'content-type: application/json' \
  -d '{"kind":"mcp_server","name":"acme-mcp","version":"2.1.0","provenance":{"signed":true,"publisherVerified":true,"sourceRepo":"https://github.com/acme/mcp"},"permissions":["tool.invoke"]}'

Response

FieldTypeNotes
riskScoreintegerRange 0…100.
severityCountsobject
findingsobject[]
POST/v1/scans/batch

Scan up to 100 components in one call (CI use case)

API key requiredQuota: no fixed cost

Quota cost scales with the batch — a 50-dependency pipeline run bills 50, never 1.

Try itPOST /v1/scans/batchQuota: no fixed cost

Runs against your real account. The contract gives this endpoint no fixed quota cost: nothing is reserved before it runs, and endpoints whose work scales with the payload reserve an amount derived from the body instead — so a large request here can cost more than one unit. Send a small one first.

Using the API key from the playground key fieldno key set yet. It is sent only in the Authorization: Bearer header, only to https://agentsupplytrust-api.com.

The contract declares no example for this endpoint, so this body was built from its schema. Check the field table below before sending.

Ready

Request body

FieldTypeNotes
componentsobject[]requiredAt least 1. At most 100.
policyobjectoptional

curl

curl -X POST https://agentsupplytrust-api.com/v1/scans/batch \
  -H "Authorization: Bearer $KEY"

Response

POST/v1/verdicts

Scan and apply a policy — returns an auditable allow/warn/deny

API key requiredBillable — 1 unit or more

The billable artifact. Carries a policy version and a SHA-256 component digest, so the same policy against the same component reproduces the same decision months later. Severity gates before score: any critical finding denies, since exec+network alone is enough to fetch and run arbitrary code.

Try itPOST /v1/verdictsBillable — 1 unit or more

Runs against your real account. The contract states no fixed quota cost, so one unit is reserved before the call runs — and an endpoint whose work scales with what you send can bill more than that. Read the description above, and start with a small request.

Using the API key from the playground key fieldno key set yet. It is sent only in the Authorization: Bearer header, only to https://agentsupplytrust-api.com.

Ready

Request body

FieldTypeNotes
componentobjectrequired
policyobjectoptional

Example request

{
  "component": {
    "kind": "mcp_server",
    "name": "postmark-mcp",
    "version": "1.0.3",
    "provenance": {
      "signed": false,
      "publisherVerified": false
    },
    "permissions": [
      "network.outbound",
      "process.exec",
      "credentials.read"
    ]
  }
}

curl

curl -X POST https://agentsupplytrust-api.com/v1/verdicts \
  -H "Authorization: Bearer $KEY" \
  -H 'content-type: application/json' \
  -d '{"component":{"kind":"mcp_server","name":"postmark-mcp","version":"1.0.3","provenance":{"signed":false,"publisherVerified":false},"permissions":["network.outbound","process.exec","credentials.read"]}}'

Response

FieldTypeNotes
verdictobject
scanobject
POST/v1/demo/scan

Public demo — scan components without a key

No key required

Runs the real trust engine over the components you supply. Capped in size, nothing is stored, nothing is metered. Use it to see the risk findings before you integrate.

Try itPOST /v1/demo/scanNo key required

Public endpoint. No API key, no quota, nothing billed.

The contract declares no request schema for this endpoint, so there is nothing to prefill. See the description above for what it accepts.

Ready

curl

curl -X POST https://agentsupplytrust-api.com/v1/demo/scan

Response

Account, keys and billing

Issue and rotate keys, read your usage against the plan allowance, change or cancel that plan, and pull invoices and payments — plus the two unauthenticated service endpoints. Nothing here is specific to this product: it is the account surface that sits behind every key this API issues.

POST/v1/keys

Request a free sandbox API key (sends a verification email)

No key required

Starts self-serve key issuance. A one-time claim token is emailed to the address you supply; POST it to /v1/keys/claim to receive the key. No key is returned here, and the response is the same whether or not that address already has an account — so this endpoint cannot be used to find out who has one. The email is verified because your account, your usage and your invoice are all keyed to it: issuing on an unverified address would let anyone mint a working key on your account and spend your allowance. Keep using the same address and a paid plan bought with it raises the keys you already hold rather than issuing new ones. Distributed integrations may identify their discovery surface with the optional source object or x-integration-source header; invalid source values are ignored and never block key issuance.

Try itPOST /v1/keysNo key required

Public endpoint. No API key, no quota, nothing billed.

Ready

Request body

FieldTypeNotes
emailstringrequiredWhere the claim token is sent. This becomes your account. Format: email.
namestringoptionalOptional label for the key, e.g. "staging". Shown in GET /v1/keys.
sourceobjectoptionalOptional discovery metadata supplied by a README, SDK, Postman collection or MCP client.

Example request

{
  "email": "you@example.com",
  "name": "staging",
  "source": {
    "source": "web",
    "medium": "docs"
  }
}

curl

curl -X POST https://agentsupplytrust-api.com/v1/keys \
  -H 'content-type: application/json' \
  -d '{"email":"you@example.com","name":"staging","source":{"source":"web","medium":"docs"}}'

Response

FieldTypeNotes
status"verification_sent"
emailstringFormat: email.
expiresAtstringAfter this, request a new one. Format: date-time.
nextstringThe endpoint that turns the emailed token into a key.
messagestring
requestIdstring
GET/v1/keys

List your API keys for this API

API key requiredFree — no quota

Every key on YOUR account for this API — label, non-secret prefix, status, when it was created, when it was last used, and what it has consumed this period. Authenticate with any active key on the account; the account is taken from that key, never from a parameter, so this can only ever return your own keys. Keys you hold for other APIs in the portfolio are not listed here. Secrets are not returned and cannot be: only a peppered hash is stored. Free, and consumes no quota.

Try itGET /v1/keysFree — no quota

Needs your API key. The contract gives this endpoint no quota cost and it takes no request body, so nothing is reserved and nothing is billed.

Using the API key from the playground key fieldno key set yet. It is sent only in the Authorization: Bearer header, only to https://agentsupplytrust-api.com.

Ready

curl

curl -X GET https://agentsupplytrust-api.com/v1/keys \
  -H "Authorization: Bearer $KEY"

Response

FieldTypeNotes
productstring
accountIdstring
keysobject[]
requestIdstring
POST/v1/keys/claim

Exchange an emailed claim token for the API key

No key required

Spends the token emailed by POST /v1/keys and returns the key. The key is shown ONCE — only a peppered hash is stored, so it can never be read back; if you lose it, rotate. The key works only on this API, and the allowance it is issued with reflects your account: your paid plan when you have one, the free sandbox allowance when you do not.

Try itPOST /v1/keys/claimNo key required

Public endpoint. No API key, no quota, nothing billed.

Ready

Request body

FieldTypeNotes
tokenstringrequiredThe claim token from the verification email.

Example request

{
  "token": "eyJ2IjoxLCJlIjoieW91QGV4YW1wbGUuY29tIn0.ZXhhbXBsZQ"
}

curl

curl -X POST https://agentsupplytrust-api.com/v1/keys/claim \
  -H 'content-type: application/json' \
  -d '{"token":"eyJ2IjoxLCJlIjoieW91QGV4YW1wbGUuY29tIn0.ZXhhbXBsZQ"}'

Response

FieldTypeNotes
apiKeystringShown once and never again. Store it now.
keyIdstringUse this with /v1/keys/{id}/revoke and /v1/keys/{id}/rotate.
productstringThe key works only on this API.
quotaPerPeriodinteger | null
planstringThe tier this allowance came from, or "sandbox" on the free tier.
warningstring
usagestring
requestIdstring
POST/v1/keys/{id}/rotate

Replace one of your API keys with a new secret

API key requiredQuota: no fixed cost

Issues a replacement key and revokes the old one. This is the answer to a leaked or lost key: the new secret is returned once, the old secret stops working immediately, and the label carries over unless you supply a new one. The replacement is issued at your account's current allowance — your paid plan if you have one — not at the old key's. Rotating does not count against the active-key limit, because it replaces rather than adds. Free, and it works while you are out of quota.

Try itPOST /v1/keys/{id}/rotateQuota: no fixed cost

Runs against your real account. The contract gives this endpoint no fixed quota cost: nothing is reserved before it runs, and endpoints whose work scales with the payload reserve an amount derived from the body instead — so a large request here can cost more than one unit. Send a small one first.

Using the API key from the playground key fieldno key set yet. It is sent only in the Authorization: Bearer header, only to https://agentsupplytrust-api.com.

Ready

Request body

FieldTypeNotes
namestringoptionalOptional new label. Defaults to the old key's.

Example request

{
  "name": "production (rotated)"
}

curl

curl -X POST https://agentsupplytrust-api.com/v1/keys/{id}/rotate \
  -H "Authorization: Bearer $KEY" \
  -H 'content-type: application/json' \
  -d '{"name":"production (rotated)"}'

Response

FieldTypeNotes
apiKeystringThe new secret. Shown once.
keyIdstring
replacedstringThe id of the key that was revoked.
productstring
quotaPerPeriodinteger | null
planstring
warningstring
requestIdstring
POST/v1/keys/{id}/revoke

Revoke one of your API keys

API key requiredFree — no quota

Kills a key immediately: the very next request made with it is refused with 401 invalid_api_key. There is no propagation delay and no cache to wait out. You may revoke the key you are authenticating with — that is the correct move when it has leaked, though you will then need another key, or the email flow, to get back in; rotate does both in one call. A key belonging to another account, or to another API, answers 404 exactly as an unknown id does, so this cannot be used to probe for keys you do not own. Idempotent, and free.

Try itPOST /v1/keys/{id}/revokeFree — no quota

Needs your API key. The contract gives this endpoint no quota cost and it takes no request body, so nothing is reserved and nothing is billed.

Using the API key from the playground key fieldno key set yet. It is sent only in the Authorization: Bearer header, only to https://agentsupplytrust-api.com.

The contract declares no request schema for this endpoint, so there is nothing to prefill. See the description above for what it accepts.

Ready

curl

curl -X POST https://agentsupplytrust-api.com/v1/keys/{id}/revoke \
  -H "Authorization: Bearer $KEY"

Response

FieldTypeNotes
idstring
status"revoked"
messagestring
requestIdstring
GET/v1/usage

Your consumption and remaining allowance for this period

API key requiredFree — no quota

Reports what YOUR ACCOUNT has consumed in the current quota period, the ceiling being enforced against it, and when that ceiling resets. The allowance belongs to the account, not to a key: every key you hold for this API draws on the same budget, so "used" is the total across all of them and a new key does not arrive with a fresh one. Free, and it consumes no quota, so it still answers once you are getting 429 quota_exceeded — which is the point: compare "used" against "ceiling" and read "period.resetsAt" to tell a period you have simply exhausted from a plan that is no longer active, which shows as a "status" of canceled and a ceiling of 0. "used" counts billing units (see "unit"), not HTTP requests: a single request can consume several. All money is in integer minor units (cents), never a decimal. The period reported here is the quota period — the calendar month in UTC, resetting at 00:00 UTC on the 1st. Your invoice window is anchored to the date you subscribed and is a different window; the amounts here are what this period’s usage has accrued so far, not a bill.

Try itGET /v1/usageFree — no quota

Needs your API key. The contract gives this endpoint no quota cost and it takes no request body, so nothing is reserved and nothing is billed.

Using the API key from the playground key fieldno key set yet. It is sent only in the Authorization: Bearer header, only to https://agentsupplytrust-api.com.

Ready

curl

curl -X GET https://agentsupplytrust-api.com/v1/usage \
  -H "Authorization: Bearer $KEY"

Response

FieldTypeNotes
productstringThe API this key is bound to. A key works only on one.
tierstring | nullThe plan tier you are billed on, e.g. "developer". Null on a free sandbox key with no paid plan.
status"sandbox" | "active" | "past_due" | "canceled"State of your plan. "sandbox" means no paid plan; "canceled" explains a ceiling of 0.
unitstringThe billing unit this API meters. "used", "included", "ceiling" and "remaining" are all counted in these, not in requests.
periodobjectThe quota period: the calendar month in UTC.
includedintegerUnits your flat monthly fee already covers, before overage pricing applies. 0 without a paid plan.
usedintegerUnits your account has consumed so far this period, summed across every key you hold for this API.
ceilinginteger | nullThe hard limit enforced against your ACCOUNT: requests on any of its keys are refused once the total passes it. Null means unlimited.
remaininginteger | nullceiling minus used, never below 0. Null when the ceiling is unlimited.
overageSoFarMinorintegerWhat this period’s usage beyond "included" has accrued, in minor units, before your spend cap is applied. 0 without a paid plan.
spendCapMinorintegerThe most the overage part of one period can ever cost you, in minor units. Your flat base fee is separate and is never capped away.
requestIdstringQuote this when reporting a problem.
POST/v1/checkout

Start a hosted Square checkout for a paid tier

No key required

Returns a Square-hosted payment URL for the requested tier. No API key is needed — a prospect has not got one yet. The email Square collects becomes the account, so a key issued later for the same address inherits the paid quota. Enterprise returns a contact route rather than a payment link. THIS IS THE PATH FOR SOMEONE WHO IS NOT YET PAYING. It starts a NEW Square recurring subscription, so it is refused with 409 `conflict` (`details.reason` `existing_subscription`) when the request carries a dashboard session for an account that already has a live plan on this API — a second subscription would be charged alongside the first, every month, and this API cannot cancel either one. Change tier with POST /v1/subscription/plan, or, when Square collects your base fee, cancel it with Square first.

Try itPOST /v1/checkoutNo key required

Public endpoint. No API key, no quota, nothing billed.

Ready

Request body

FieldTypeNotes
tierstringrequireddeveloper | growth | scale | enterprise

Example request

{
  "tier": "developer"
}

curl

curl -X POST https://agentsupplytrust-api.com/v1/checkout \
  -H 'content-type: application/json' \
  -d '{"tier":"developer"}'

Response

FieldTypeNotes
checkoutUrlstringSquare-hosted payment page. Redirect the buyer here. Format: uri.
tierstring
skustring
requestIdstring
GET/v1/subscription

Your current plan, billing window and available changes (dashboard session required)

No key required

Reports the plan this account is on, the billing window it is in, any tier change already staged for the next invoice, and the full pricing ladder marked up so you can see which rungs are an upgrade and which a downgrade. `planChangesGoThrough` is the field to branch on: `self_serve` means POST /v1/subscription/plan can move you; `provider_managed` means Square’s own recurring subscription holds your price and neither this API nor a new checkout can move it — buying again would create a SECOND Square subscription and charge you twice; `checkout` appears only when you have no plan at all, where starting one is exactly right. All money is in integer minor units (cents). AUTHENTICATION IS YOUR DASHBOARD SESSION, NOT AN API KEY. Send the `@sp/core` session cookie this API sets when you sign in, from the same origin. An API key is refused here on purpose: it is a data-plane credential that lives in CI and in third-party integrations, and it must never be able to change what you are billed, cancel your account, or read your payment history. Errors: 401 `unauthenticated` when there is no valid session, 403 `forbidden` when the request is cross-origin or its `x-csrf-token` header is missing or wrong.

Try itGET /v1/subscriptionSign-in required

Needs a signed-in dashboard session, not an API key. Your account comes from the session cookie, so this cannot be called with a bearer token and cannot act on another account.

Ready

curl

curl -X GET https://agentsupplytrust-api.com/v1/subscription

Response

FieldTypeNotes
productstring
subscribedbooleanFalse when this account has never had a paid plan on this API.
status"sandbox" | "active" | "past_due" | "canceled""sandbox" when there is no paid plan at all — the same vocabulary GET /v1/usage reports.
planobject | nullThe tier in force right now.
pendingPlanobject | nullA tier change already staged, applied when the current window is invoiced.
planChangesGoThrough"self_serve" | "provider_managed" | "checkout"`self_serve` — POST /v1/subscription/plan moves you. `provider_managed` — Square holds your recurring price; the tier cannot be moved from here and starting a new checkout would duplicate the subscription. `checkout` — no plan yet, so POST /v1/checkout is where one starts.
baseFeeOwner"internal" | "provider"Who collects the flat monthly fee: us, or Square’s own recurring subscription.
cancellationobjectWhat cancelling would do, stated before you do it.
tiersobject[]The published ladder, each rung marked current / upgrade / downgrade.
requestIdstring
POST/v1/subscription/plan

Upgrade or downgrade to another plan (dashboard session required)

No key required

Moves this account to another rung of the published pricing ladder and re-derives the ceiling enforced against every API key on it, so an upgrade is usable immediately rather than at the next invoice. The change is STAGED, not overwritten: the current billing window is closed at this instant and priced against the tier that was actually in force for it, and the incoming tier opens the next window with the original billing anniversary preserved. A downgrade therefore never re-prices days you already consumed on the dearer plan. Refused with 409 `conflict` (`details.reason` `provider_owned_base_fee`) when Square’s own recurring subscription holds your price (`baseFeeOwner` is `provider`) — read `planChangesGoThrough` from GET /v1/subscription first. That case cannot be moved from here at all: this API holds no Square subscription of yours to change, and POST /v1/checkout would create a SECOND one and charge you for both. Cancel with Square and buy the tier you want, or contact support. AUTHENTICATION IS YOUR DASHBOARD SESSION, NOT AN API KEY. Send the `@sp/core` session cookie this API sets when you sign in, from the same origin. An API key is refused here on purpose: it is a data-plane credential that lives in CI and in third-party integrations, and it must never be able to change what you are billed, cancel your account, or read your payment history. Errors: 401 `unauthenticated` when there is no valid session, 403 `forbidden` when the request is cross-origin or its `x-csrf-token` header is missing or wrong.

Try itPOST /v1/subscription/planSign-in required

Needs a signed-in dashboard session, not an API key. Your account comes from the session cookie, so this cannot be called with a bearer token and cannot act on another account.

Ready

Request body

FieldTypeNotes
planIdstringrequiredTier id from GET /v1/subscription `tiers[].id`, e.g. "growth".

Example request

{
  "planId": "growth"
}

curl

curl -X POST https://agentsupplytrust-api.com/v1/subscription/plan \
  -H 'content-type: application/json' \
  -d '{"planId":"growth"}'

Response

FieldTypeNotes
changedboolean
direction"upgrade" | "downgrade"
fromstring
tostring
entitlementobjectThe ceiling now enforced on this account’s keys, and when it took effect.
billingobjectWhich tier the closed window is priced against, and when the new one starts.
requestIdstring
POST/v1/subscription/cancel

Cancel this plan and end metered access (dashboard session required)

No key required

Cancels the plan and drops every API key on this account for this product to a ceiling of 0, so access ends at the moment you cancel rather than at some later date nothing would enforce. The window you cancel in is closed and invoiced first, prorated to that instant: the elapsed share of the base fee plus any overage you accrued, still under the same spend cap. The invoice it writes is returned as `finalInvoice` and appears in GET /v1/invoices. When Square’s own recurring subscription collects your flat monthly fee (`baseFeeOwner` is `provider`) this API cannot stop that charge, so the request is refused with 409 unless you send `acknowledgeProviderBilling: true` — that flag exists so nobody ends up with a ceiling of zero and a live monthly charge without having been told first. AUTHENTICATION IS YOUR DASHBOARD SESSION, NOT AN API KEY. Send the `@sp/core` session cookie this API sets when you sign in, from the same origin. An API key is refused here on purpose: it is a data-plane credential that lives in CI and in third-party integrations, and it must never be able to change what you are billed, cancel your account, or read your payment history. Errors: 401 `unauthenticated` when there is no valid session, 403 `forbidden` when the request is cross-origin or its `x-csrf-token` header is missing or wrong.

Try itPOST /v1/subscription/cancelSign-in required

Needs a signed-in dashboard session, not an API key. Your account comes from the session cookie, so this cannot be called with a bearer token and cannot act on another account.

Ready

Request body

FieldTypeNotes
acknowledgeProviderBillingbooleanoptionalRequired only when `baseFeeOwner` is `provider`: confirms you understand Square will keep charging the monthly fee until you stop it there.

Example request

{
  "acknowledgeProviderBilling": true
}

curl

curl -X POST https://agentsupplytrust-api.com/v1/subscription/cancel \
  -H 'content-type: application/json' \
  -d '{"acknowledgeProviderBilling":true}'

Response

FieldTypeNotes
canceledboolean
canceledAtstringFormat: date-time.
entitlementobjectThe ceiling now enforced. 0 — access has ended.
moneyobjectExactly what happens to the charges, per base-fee owner.
finalInvoiceobject | nullThe invoice written for the window you cancelled in, or null when nothing had accrued.
requestIdstring
GET/v1/invoices

Every invoice issued against this account, newest first (dashboard session required)

No key required

Returns the stored `api_plan_invoices` rows for this account and this API — the rows the billing run actually wrote, never a reconstruction. Each one reconciles against itself: the included allowance and base fee shown are the PRORATED figures applied to that window, `overageMinorRaw` is the uncapped overage and `overageMinorCapped` is what was charged, and `baseChargedMinor` says how much of the base fee this invoice collected — 0 when Square’s recurring subscription had already taken it. An account with no billing history yet gets an empty list and a `note` explaining why, never a fabricated row. AUTHENTICATION IS YOUR DASHBOARD SESSION, NOT AN API KEY. Send the `@sp/core` session cookie this API sets when you sign in, from the same origin. An API key is refused here on purpose: it is a data-plane credential that lives in CI and in third-party integrations, and it must never be able to change what you are billed, cancel your account, or read your payment history. Errors: 401 `unauthenticated` when there is no valid session, 403 `forbidden` when the request is cross-origin or its `x-csrf-token` header is missing or wrong.

Try itGET /v1/invoicesSign-in required

Needs a signed-in dashboard session, not an API key. Your account comes from the session cookie, so this cannot be called with a bearer token and cannot act on another account.

Ready

curl

curl -X GET https://agentsupplytrust-api.com/v1/invoices

Response

FieldTypeNotes
productstring
countinteger
notestring | nullPresent only when the list is empty: says why, in a sentence a customer can act on.
invoicesobject[]
requestIdstring
GET/v1/payments

Every payment attempted against this account and how it went (dashboard session required)

No key required

The money movements behind your invoices, newest first: what was charged, whether it succeeded, and the processor’s payment id when it did. A billing period that came to nothing produces NO row here — it was closed without asking the processor for anything, and listing it would show you a payment that never happened. A failed attempt does appear, with its reason, because that is why an account goes past due. AUTHENTICATION IS YOUR DASHBOARD SESSION, NOT AN API KEY. Send the `@sp/core` session cookie this API sets when you sign in, from the same origin. An API key is refused here on purpose: it is a data-plane credential that lives in CI and in third-party integrations, and it must never be able to change what you are billed, cancel your account, or read your payment history. Errors: 401 `unauthenticated` when there is no valid session, 403 `forbidden` when the request is cross-origin or its `x-csrf-token` header is missing or wrong.

Try itGET /v1/paymentsSign-in required

Needs a signed-in dashboard session, not an API key. Your account comes from the session cookie, so this cannot be called with a bearer token and cannot act on another account.

Ready

curl

curl -X GET https://agentsupplytrust-api.com/v1/payments

Response

FieldTypeNotes
productstring
countinteger
notestring | null
paymentsobject[]
requestIdstring
GET/

Service index — endpoints, auth and error format

No key required
Try itGET /No key required

Public endpoint. No API key, no quota, nothing billed.

Ready

curl

curl -X GET https://agentsupplytrust-api.com/

Response

GET/health

Liveness and deployed version

No key required
Try itGET /healthNo key required

Public endpoint. No API key, no quota, nothing billed.

Ready

curl

curl -X GET https://agentsupplytrust-api.com/health

Response

Errors

Every failure returns the same shape. Branch on code — it is a stable enum. message is for humans and may change.

{
  "error": {
    "code": "quota_exceeded",
    "message": "Quota exceeded for this billing period.",
    "requestId": "0f3c8b12-…"
  }
}
CodeHTTPMeaning
missing_api_key401No Authorization or x-api-key header
invalid_api_key401Unknown, revoked, or issued for a different API
quota_exceeded429Allowance used for this period
rate_limited429Too many requests
invalid_request400Validation failed — details.path names the exact field
not_found404No such route or resource
internal_error500Our fault, not yours

Two codes return 429 and they mean different things. quota_exceeded is the allowance for the billing period; it clears at the next period or on upgrade. rate_limited is a per-minute ceiling on the key. Unless a ceiling has been set explicitly for the key, it is derived from the key's period allowance: one hour's share of the month (allowance ÷ 720, rounded up, never below 60) may be spent in any single minute — so a plan with more volume also gets a higher ceiling. Both codes carry a Retry-After header in whole seconds (RFC 9110) computed from the real reset time, never a fixed constant, so honour it rather than guessing a back-off.

requestId appears on every response — success or failure — and in the x-request-id header. Quote it and we can find the exact request. The playground shows it above each response.

SDKs

Single files, zero dependencies — no requests, no axios — so they drop into any environment without a dependency negotiation.

Python

from supply_chain_trust import SupplyChainTrust

client = SupplyChainTrust()                 # reads SUPPLY_CHAIN_TRUST_API_KEY

# One component per call. Use /v1/scans/batch for many.
res = client.scan({
    "kind": "mcp_server",
    "name": "acme-mcp",
    "version": "2.1.0",
    "provenance": {"signed": True, "publisherVerified": True,
                   "sourceRepo": "https://github.com/acme/mcp"},
    "permissions": ["tool.invoke"],
})

print("risk score", res["riskScore"], res["severityCounts"])

for f in res["findings"]:
    # facet says which dimension failed; code is the stable enum to branch on.
    print(f["severity"], f["code"], f["facet"], f["message"])

TypeScript

import { SupplyChainTrust } from './supply-chain-trust.js'

const client = new SupplyChainTrust()       // reads SUPPLY_CHAIN_TRUST_API_KEY

// One component per call. Use /v1/scans/batch for many.
const res = await client.scan({
  kind: 'mcp_server',
  name: 'acme-mcp',
  version: '2.1.0',
  provenance: { signed: true, publisherVerified: true,
                sourceRepo: 'https://github.com/acme/mcp' },
  permissions: ['tool.invoke'],
})

console.log('risk score', res.riskScore, res.severityCounts)

for (const f of res.findings) {
  // `facet` says which dimension failed; branch on `code`.
  console.log(f.severity, f.code, f.facet, f.message)
}

Download

FileSizeNotes
Python SDK supply_chain_trust.py14.5 kBSingle file, no dependencies — no requests, no httpx. Python 3.9+.
TypeScript SDK supply_chain_trust.ts15.8 kBSingle file, no dependencies — no axios, no node-fetch. Node 18+, Deno, Bun and Workers.
Postman collection postman_collection.json23.6 kBEvery endpoint, generated from the same contract as this page. Import it and set the key variable.

These are the files from the repo, published here so they are reachable from the site rather than only from a checkout. They are regenerated with this page, so what you download is the version this reference describes.