Sharp TrustSHARP LABS
Sharp Trust/Merchant API docs
Integration question? Contact us ↗
API REFERENCEBuild with the complete contract.

Sharp Trust, Merchant and PSP Integration Guide

Version: v3 · August 2026

Sharp Trust gives you a real-time risk decision on each agent-initiated transaction, before you authorize it. You send us the transaction, we return a recommendation (APPROVE, REVIEW, or DECLINE) with three separate scores and the reasons. That is the whole integration: one call in, one decision out.

You never send us a card number, CVV, or any payment credential. We only need transaction context. Staying out of your PCI scope is by design.


Getting started

  1. Open the partner portal (or click Get a test key from the docs).
  2. Sign in with Google (any verified work account).
  3. Set your organization name and type (Merchant or PSP).
  4. Click Create / rotate test key and copy the key immediately, it is shown once.
  5. Use Try the API on the same page (your key never goes in the browser), or call the API with curl or Postman (see below).

Test keys look like shai_test_... and are self-serve from the portal. Live keys (shai_live_...) are issued manually after production onboarding, email contact@sharp-labs.com.


The whole thing in one call

POST https://trust.sharp-labs.com/v1/assessments
Authorization: Bearer <your-api-key>
Content-Type: application/json

Send your API key on every request as Authorization: Bearer <key> (or an X-API-Key header). Keep it in your server's secrets, never in a browser or a public repo. You can rotate it from the portal at any time; each merchant's key is separate.

Minimum request (this is genuinely all that is required):

{
  "platform_transaction_ref": "your-own-transaction-id",
  "buyer_agent": { "external_ref": "the-agent-identifier" },
  "amount": { "value": "48.00", "currency": "USD" },
  "merchant_meta": { "name": "acme-subscriptions" }
}

Response:

{
  "decision": "REVIEW",
  "recommendation": "REVIEW",
  "trust_score": 0.7,
  "agent_trust": 0.7,
  "transaction_risk": 0.3,
  "confidence": 0.5,
  "evidence_confidence": 0.5,
  "reason_codes": [
    "SIGNATURE_NOT_PROVIDED",
    "SESSION_NOT_PROVIDED",
    "MANDATE_NOT_PROVIDED",
    "NO_VELOCITY_BASELINE",
    "NEW_AGENT_LOW_HISTORY",
    "CONTEXT_DEFAULT_PRIOR",
    "SELLER_LOW_HISTORY"
  ],
  "assessment_id": "0716d54b-c12f-4a36-a58c-5d42c6388fee",
  "audit_ref": "audit_0716d54b-c12f-4a36-a58c-5d42c6388fee",
  "created_at": "2026-08-24T21:10:00.000Z"
}

That is the expected cold-start shape for the minimum request. It is accepted, but returns REVIEW because no identity, mandate, or history was supplied. The score is low because coverage is low, not because the transaction is risky. That is why we return the three outputs below, so you can tell those two situations apart.


Three outputs, plus a recommendation

A single number cannot tell you whether a low score means genuine risk or simply not enough evidence. So every assessment returns three separate outputs:

Output What it means Range
agent_trust Trust in the agent and its authorization (identity, session, mandate, agent reputation). 0 to 1, higher is safer
transaction_risk Risk of this specific transaction (velocity, intent, merchant). 0 to 1, higher is riskier
evidence_confidence How much real evidence backed the assessment (coverage). Low here means "not enough data," not "risky." 0 to 1

Then a single recommendation you act on:

recommendation decision What you do
APPROVE PROCEED Continue to authorization
REVIEW REVIEW Your choice: hold, step up, or continue with caution
DECLINE BLOCK Stop the transaction
DECLINE BLOCKED_BY_SCHEME The network declined it (only if you opt into scheme checks)

recommendation and decision always agree; recommendation is the plain APPROVE / REVIEW / DECLINE label, decision is the internal value. Use whichever your systems prefer.

That is a complete integration. Everything below is optional and only makes the decision sharper.


Try it

export SHARP_TRUST_URL="https://trust.sharp-labs.com"
export SHARP_TRUST_KEY="<your-shai_test-key>"

curl -sS -X POST "$SHARP_TRUST_URL/v1/assessments" \
  -H "Authorization: Bearer $SHARP_TRUST_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: demo-$(date +%s)" \
  -d '{
    "platform_transaction_ref": "your-own-transaction-id",
    "buyer_agent": { "external_ref": "the-agent-identifier" },
    "amount": { "value": "48.00", "currency": "USD" },
    "merchant_meta": { "name": "acme-subscriptions" }
  }'

Import the Postman collection into Postman, set apiKey, and send the same request. The full machine contract is at /docs/openapi.yaml.


Request fields

Required

Field Type Notes
platform_transaction_ref string Your transaction id, retained for correlation and audit.
buyer_agent object The paying agent. { "external_ref": "..." } is enough.
amount object { "value": "48.00", "currency": "USD" }. Value is a decimal string.

Recommended (cheap to send, improves accuracy)

Field Type Notes
merchant_meta object The seller: { "name": "acme", "url": "acme.com", "lei": "..." }. url and lei unlock merchant-legitimacy checks (domain age, certificate transparency, GLEIF).
seller_agent object The seller agent, { "external_ref": "..." }, for counterparty reputation.
intent_summary string What the user asked for, e.g. "Subscribe to Acme Pro".

Optional evidence (send whatever you already have)

All evidence goes under an evidence object. Missing fields lower confidence, they never cause an error.

Field What it adds
evidence.mandates The user's authorization. { "amount_cap": "100.00", "currency": "USD", "counterparty": "acme", "effective_until": "2030-01-01T00:00:00Z" }. Optional amount_tolerance_percent / amount_tolerance_fixed for tax, shipping, tips, FX, and pre-authorization drift. See Assurance levels below. If you use Basis Theory, send { "allowance_id": "alw_..." } and we fetch it. For a natural-language authorization, send { "instruction": "spend up to $100 at Acme by Friday" } and we derive the mandate (marked as inferred assurance). AP2 verifiable mandates go in { "ap2": { ... } }.
evidence.agent_signature A signed request proving the agent's identity: a Visa TAP signature, or an open Web Bot Auth signature verified against the provider's own key directory (add signature_agent). Add source_ip and we cross-check it against the provider's published infrastructure.
evidence.intent { "instruction": "...", "agent_context": "...", "item_description": "..." }. We scan agent_context (the untrusted text the agent read) for prompt-injection, and flag purchases that diverge from the user's intent.
evidence.session Consumer / session assurance: { "human_verified": true, "session_bound": true, "delegation": { "scopes": [...], "expires_at": "..." }, "provider": "..." }. A valid agent can still act for a compromised account; this catches that.
require_scheme_check boolean. Ask us to also run a network scheme check.

Idempotency: send an Idempotency-Key header with your transaction id to make retries safe. Idempotency is isolated per merchant.


Assurance levels

An authorization interpreted from natural language must not carry the same weight as one that is cryptographically signed. A consistent mandate is capped by how strongly it is backed:

Level Source Max weight Reason code
Inferred Derived from a free-text instruction 0.60 MANDATE_ASSURANCE_INFERRED
User-confirmed The user confirmed the interpreted mandate (user_confirmed: true) 0.78 MANDATE_ASSURANCE_USER_CONFIRMED
Authenticated Supplied over your authenticated channel 0.95 MANDATE_ASSURANCE_AUTHENTICATED
Cryptographic Signed mandate or network-confirmed (e.g. a customer-approved Basis Theory allowance, or a verified AP2 proof) 0.98 MANDATE_ASSURANCE_CRYPTOGRAPHIC

A mandate mismatch (amount, merchant, expiry) still blocks regardless of assurance. An amount over the cap but within tolerance passes with MANDATE_AMOUNT_WITHIN_TOLERANCE.


Response fields

Field Meaning
recommendation APPROVE / REVIEW / DECLINE
decision PROCEED / REVIEW / BLOCK / BLOCKED_BY_SCHEME
trust_score 0 to 1, overall, higher is safer
agent_trust 0 to 1, trust in the agent and its authorization
transaction_risk 0 to 1, risk of this transaction, higher is riskier
evidence_confidence (and confidence) 0 to 1, how much real evidence we had
reason_codes Machine-readable reasons, see the catalog below
assessment_id Our id for this decision
audit_ref Reference for dispute evidence
created_at Timestamp

Store assessment_id and audit_ref against your transaction. They are your evidence trail.


Reason code catalog

Reason codes are stable strings. New ones may be added; treat unknown codes as informational.

Identity and session (agent_trust) AGENT_SIGNATURE_VALID, TAP_SIGNATURE_VALID, AGENT_INFRA_CORROBORATED, AGENT_INFRA_MISMATCH, AGENT_IP_PRIVATE, SIGNATURE_NOT_PROVIDED, TAP_SIGNATURE_INVALID, TAP_REPLAY_DETECTED, TAP_KEY_EXPIRED, SESSION_VERIFIED, SESSION_WEAK, SESSION_UNVERIFIED, SESSION_DELEGATION_EXPIRED, SESSION_ACCOUNT_COMPROMISED, SESSION_NOT_PROVIDED.

Mandate (agent_trust) MANDATE_CONSISTENT, MANDATE_ASSURANCE_INFERRED, MANDATE_ASSURANCE_USER_CONFIRMED, MANDATE_ASSURANCE_AUTHENTICATED, MANDATE_ASSURANCE_CRYPTOGRAPHIC, MANDATE_AMOUNT_MISMATCH, MANDATE_AMOUNT_WITHIN_TOLERANCE, MANDATE_CURRENCY_MISMATCH, MANDATE_COUNTERPARTY_MISMATCH, MANDATE_COUNTERPARTY_APPROX, MANDATE_EXPIRED, MANDATE_INVALID, MANDATE_NOT_FOUND, MANDATE_NOT_PROVIDED.

Intent and context (transaction_risk) INTENT_MATCH, INTENT_CLEAN, INTENT_PURCHASE_DIVERGENCE, PROMPT_INJECTION_DETECTED, PROMPT_INJECTION_SUSPECTED, INTENT_NOT_PROVIDED, CONTEXT_DEFAULT_PRIOR.

Velocity (transaction_risk) VELOCITY_NORMAL, VELOCITY_ELEVATED, VELOCITY_HIGH, AMOUNT_SPIKE, NO_VELOCITY_BASELINE.

Reputation (agent and seller) AGENT_TRUSTED_HISTORY, AGENT_CROSS_CLIENT_TRUST, AGENT_DISPUTE_HISTORY, AGENT_CHARGEBACK_HISTORY, AGENT_FRAUD_HISTORY, AGENT_FRAUD_UNVERIFIED, AGENT_REPUTATION_UNCORROBORATED, NEW_AGENT_LOW_HISTORY, and the SELLER_... equivalents.

Merchant legitimacy (transaction_risk) MERCHANT_ESTABLISHED, MERCHANT_LEGITIMACY_OK, MERCHANT_LEI_VERIFIED, MERCHANT_DOMAIN_NEW, MERCHANT_DOMAIN_VERY_NEW, MERCHANT_MALICIOUS_DOMAIN, MERCHANT_LEGITIMACY_UNKNOWN.

Add ?explainability=full support via the explainability field to receive a plain-English explanations map for the codes on a given decision.


Tell us the outcome (closes the loop)

When you know what happened to a transaction, report it. Outcomes drive cross-client reputation and give you validated ROI. This is a formal contract, not just chargebacks:

POST /v1/outcomes
Authorization: Bearer <your-api-key>
Content-Type: application/json

{
  "transaction_ref": "your-own-transaction-id",
  "type": "chargeback",
  "final": true,
  "source": "network",
  "occurred_at": "2026-08-24T12:00:00Z",
  "amount": 48.00
}
Field Notes
transaction_ref The transaction this outcome belongs to (the platform_transaction_ref you sent).
type authorization, capture, settlement, reversal, refund, dispute, chargeback, or fraud.
final true for a final outcome, false for a preliminary one. Only final, reputationally-meaningful outcomes move reputation.
source Who reported it: network, psp, merchant, or platform. More authoritative sources carry more weight.
occurred_at ISO 8601 timestamp.
amount, merchant_ref, mandate_ref, agent_ref, seller_ref Optional. Opaque ids only, never a PAN.

Every outcome is written to a tamper-evident, hash-chained audit trail. Read and verify it:

GET /v1/audit-trail

Reporting outcomes is not required to start. It is the upgrade that turns "exposure blocked" into "loss avoided," and it is what makes reputation resistant to manipulation (a single non-authoritative claim is flagged, not acted on).


What you never send us

  • No PAN (card number), no CVV, no cryptogram, no usable payment credential.

We are a decision layer, not a payment processor. We stay out of your PCI scope by design.


Advisory vs block mode

  • Advisory (default): we return a recommendation and you stay in control.

Great for going live safely and comparing against your current flow.

  • Block mode: you treat DECLINE as a hard stop. Flip to this once you trust

the decisions.

Start in advisory. Move to block when you are comfortable.


To go live

  1. Integrate against /v1/assessments with your test key and validate decisions.
  2. Run in advisory alongside your current flow.
  3. Start sending outcomes to /v1/outcomes so reputation and ROI accrue.
  4. Contact contact@sharp-labs.com for a live key

(shai_live_...) and production onboarding.

  1. When you are ready, switch to block.

Questions or a field you are unsure about: reach out and we will map it with you. Integration timing depends on the merchant's environment, security review, and the signals enabled for that deployment.