SafeClick API
Enforcement API
Send the transaction or intended action before your system acts. SafeClick returns the decision your execution path must enforce.
First call
Pre-seed status: this customer ingress is defined in code and App Hosting configuration. An authenticated request on the current serving build has not yet been verified. Contact SafeClick for provisioned access before treating it as live.
https://safeclick.dev/api/restCreate a Team API key in the console, keep it on your server, then evaluate the action immediately before signing, broadcast, or execution.
curl -X POST "https://safeclick.dev/api/rest/v1/scan/transaction" \
-H "x-api-key: $SAFECLICK_API_KEY" \
-H "Idempotency-Key: $SAFECLICK_REQUEST_ID" \
-H "content-type: application/json" \
-d '{
"to": "0x52908400098527886E0F7030069857D2E4169EE7",
"value": "1000",
"network_key": "eip155:1"
}'{
"scan_id": "6d5b6c44-37d3-4d31-b6e1-3902b5c81616",
"status": "final",
"action": "ALLOW",
"validation_required": false,
"risk_tier": "low",
"reason_categories": ["policy_rule"],
"coverage_status": "complete",
"response_schema_version": "public-scan-v1"
}Enforce the decision
const result = await response.json();
const mayExecute =
result.status === "final" &&
(result.action === "ALLOW" || result.action === "FINAL_ALLOW");
if (!mayExecute) {
throw new Error("SafeClick did not allow execution");
}
await signOrExecute(transaction);| Response | Meaning | Your action |
|---|---|---|
| final · ALLOW / FINAL_ALLOW | SafeClick allows this action. | Continue under your own signing policy. |
| final · BLOCK / FINAL_BLOCK | SafeClick blocks this action. | Do not sign, broadcast, or execute. |
| processing / pending_validation | No final allow exists yet. | Stop and read the scan again by ID. |
| timeout / 401 / 429 / 5xx | SafeClick did not return a usable decision. | Do not auto-execute. |
A scan submission returns HTTP 202 even when its decision is already final. Read status and action; do not infer state from the HTTP success code.
Enforcement endpoints
| Method | Path | Purpose | Scope |
|---|---|---|---|
| POST | /v1/scan/transaction | Evaluate a transaction before execution | scan.execute |
| GET | /v1/scans/{id} | Read the current or final decision | scans.read |
Supporting analysis
These routes reuse detector capabilities behind SafeClick and the included first-party tools. They share the Team API-key scope shown below, but they are not separate products or the canonical transaction-enforcement entry point.
| Method | Path | Purpose | Scope |
|---|---|---|---|
| POST | /v1/scan/url | Run the URL detector | scan.execute |
| POST | /v1/scan/wallet | Run wallet analysis | scan.execute |
| POST | /v1/scan/contract | Run contract analysis | scan.execute |
| GET | /v1/intel/domain/{domain} | Read stored domain intelligence | intel.read |
| GET | /v1/intel/address/{address} | Read stored address intelligence | intel.read |
Team configuration
| Method | Path | Purpose | Scope |
|---|---|---|---|
| GET | /v1/access-grant | Read this Team's API access allowance and expiry | authenticated |
| GET | /v1/policies | List policy versions | policy.read |
| POST | /v1/policies | Create a policy version | policy.write |
| GET | /v1/webhooks | List webhook endpoints | webhooks.read |
| POST | /v1/webhooks | Create a webhook endpoint | webhooks.manage |
| DELETE | /v1/webhooks/{id} | Remove a webhook endpoint | webhooks.manage |
| POST | /v1/webhooks/{id}/rotate | Rotate a webhook secret | webhooks.manage |
| GET | /v1/webhooks/{id}/deliveries | Read delivery attempts | webhooks.read |
| POST | /v1/webhooks/test | Build or deliver a signed test event | webhooks.manage |
| GET | /v1/usage | Read metered API usage | usage.read |
| POST | /v1/access-requests | Request Team API access | session-only |
Decision audit trail
The Team console reads tenant-scoped audit records committed by the Enforcement pipeline. They show the decision path, actor, time, and customer-safe metadata. This is a decision audit trail, not a complete log of every administrative action.
Authentication
Send the Team API key as x-api-key or Authorization: Bearer. Keep it in a server-side secret store. Browser bundles and public repositories must not contain it.
New keys start with scan.execute and scans.read. During pre-seed, additional control-plane scopes are provisioned with SafeClick; request the scope shown beside the route before integrating it.
Keys are scoped to one Team. The API derives the Organization from the verified credential; request bodies cannot select another tenant.
Real scans require an active Team access grant from SafeClick. Check its status at GET /v1/access-grant. Configuration and existing scan reads remain available without a grant.
Set SAFECLICK_REQUEST_ID to a unique ID for each logical scan. Keep the same Idempotency-Key and payload when retrying so a completed response is replayed without another scan or charge. A new key means new work.
Errors
| 400 | The request does not match the input contract. |
| 401 | The API key is missing, invalid, expired, or revoked. |
| 403 | The credential lacks scope, or access_not_granted explains the Team's missing, disabled, expired, or exhausted allowance. |
| 404 | The Team cannot read the requested resource. |
| 409 | An idempotent request is still pending, or the same key was reused with different input. Do not retry uncertain work with a new key. |
| 429 | The caller or Team exceeded the current request budget. Honor Retry-After. |
| 503 | The enforcement pipeline did not produce a decision. |
Get an API key
Pre-seed Team and API-key access is provisioned by SafeClick. Contact us to start an integration. Existing Team operators manage credentials under API keys. The plaintext key is shown once.