{"id":47725949,"url":"https://github.com/agentscore/node-sdk","last_synced_at":"2026-05-24T08:02:40.354Z","repository":{"id":345758973,"uuid":"1187154475","full_name":"agentscore/node-sdk","owner":"agentscore","description":"TypeScript client for the AgentScore trust and reputation API","archived":false,"fork":false,"pushed_at":"2026-03-31T06:31:10.000Z","size":112,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-31T08:41:58.697Z","etag":null,"topics":["agentscore","ai-agent","blockchain","erc-8004","reputation","sdk","trust","typescript","x402"],"latest_commit_sha":null,"homepage":"https://docs.agentscore.sh","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/agentscore.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-20T12:02:07.000Z","updated_at":"2026-03-30T03:42:19.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/agentscore/node-sdk","commit_stats":null,"previous_names":["agentscore/node-sdk"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/agentscore/node-sdk","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agentscore%2Fnode-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agentscore%2Fnode-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agentscore%2Fnode-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agentscore%2Fnode-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/agentscore","download_url":"https://codeload.github.com/agentscore/node-sdk/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agentscore%2Fnode-sdk/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31315958,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T12:59:32.332Z","status":"ssl_error","status_checked_at":"2026-04-02T12:54:48.875Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agentscore","ai-agent","blockchain","erc-8004","reputation","sdk","trust","typescript","x402"],"created_at":"2026-04-02T20:27:28.414Z","updated_at":"2026-05-24T08:02:40.348Z","avatar_url":"https://github.com/agentscore.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @agent-score/sdk\n\n[![npm version](https://img.shields.io/npm/v/@agent-score/sdk.svg)](https://www.npmjs.com/package/@agent-score/sdk)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)\n\nTypeScript/Node.js client for the [AgentScore](https://agentscore.sh) APIs.\n\n## Install\n\n```bash\nnpm install @agent-score/sdk\n# or\nbun add @agent-score/sdk\n```\n\n## Quick Start\n\n```typescript\nimport { AgentScore } from \"@agent-score/sdk\";\n\nconst client = new AgentScore({ apiKey: \"as_live_...\" });\n\n// Look up cached reputation (free)\nconst rep = await client.getReputation(\"0x1234...\");\nconsole.log(rep.score.value, rep.score.grade);\n\n// Filter to a specific chain\nconst baseRep = await client.getReputation(\"0x1234...\", { chain: \"base\" });\nconsole.log(baseRep.agents); // only Base agents\n\n// Identity gate with policy (paid)\nconst gated = await client.assess(\"0x1234...\", {\n  policy: {\n    require_kyc: true,\n    require_sanctions_clear: true,\n    min_age: 21,\n  },\n});\n\nif (gated.decision === \"deny\") {\n  console.log(gated.decision_reasons); // [\"kyc_required\"]\n  console.log(gated.verify_url);       // URL for operator verification\n}\n\n// Check verification level on reputation\nconst verified = await client.getReputation(\"0x1234...\");\nconsole.log(verified.verification_level); // \"none\" | \"wallet_claimed\" | \"kyc_verified\"\n```\n\n### Credential-Based Identity\n\nAgents without wallets can use operator credentials for identity:\n\n```typescript\n// Assess with an operator credential instead of a wallet address\nconst result = await client.assess(null, { operatorToken: \"opc_...\" });\nconsole.log(result.decision); // \"allow\" | \"deny\"\n```\n\n### Verification Sessions\n\nBootstrap identity for first-time agents. The success body carries structured `next_steps` (with `action: \"deliver_verify_url_and_poll\"`) and a cross-merchant `agent_memory` hint. Poll responses carry `next_steps.action` from the typed `NextStepsAction` union (`continue_polling`, `retry_merchant_request_with_operator_token`, `use_stored_operator_token`, `create_new_session`, `verification_failed`, `contact_support`).\n\n```typescript\n// Create a session — returns a verify_url for the user and a poll_url for the agent\nconst session = await client.createSession();\nconsole.log(session.verify_url, session.poll_url, session.poll_secret);\nconsole.log(session.next_steps.action); // \"deliver_verify_url_and_poll\"\n\n// Poll until the user completes verification\nconst status = await client.pollSession(session.session_id, session.poll_secret);\nif (status.status === \"verified\") {\n  console.log(status.operator_token); // \"opc_...\" — use for future requests\n}\n\n// Optional pre-association: attach the session to a known wallet or refresh KYC\n// for an existing operator credential.\nawait client.createSession({ address: \"0x...\" });\nawait client.createSession({ operator_token: \"opc_...\" }); // KYC refresh\n```\n\n### Wallet resolution\n\n`assess()` responses include `resolved_operator` and `linked_wallets[]` — all same-operator sibling wallets (claimed via SIWE or captured via prior `associateWallet`). The list may mix EVM addresses (`0x...` lowercased) and Solana addresses (base58, case-preserved) for cross-chain operators; merchants doing wallet-signer-match checks should accept a payment signed by any address in the list, regardless of chain. The `address` parameter on `assess()` and `getReputation()` accepts either format — network is auto-detected from the address shape.\n\n### Server-side signer-match + sanctions screening\n\nPass `signer: { address, network }` on `assess()` to opt into server-side wallet-signer-match and OFAC SDN wallet-address screening on the same call. The response carries two new verdicts:\n\n```typescript\nconst result = await client.assess(\"0xclaimed...\", {\n  signer: { address: \"0xsigner...\", network: \"evm\" },\n  policy: { require_sanctions_clear: true },\n});\n\n// signer_match: wallet-binding verdict\n//   kind: 'pass' | 'wallet_signer_mismatch' | 'wallet_auth_requires_wallet_signing'\n//   plus claimed_operator / signer_operator / expected_signer / actual_signer / linked_wallets / agent_instructions\nif (result.signer_match?.kind === \"wallet_signer_mismatch\") {\n  // signer wallet resolves to a different operator than the claimed address\n}\n\n// signer_sanctions: OFAC SDN wallet-address verdict (discriminated union)\n//   { status: 'clear' } | { sanctioned: true, ofac_label, sdn_uid, listed_at } | { status: 'unavailable' }\nif (result.signer_sanctions \u0026\u0026 \"sanctioned\" in result.signer_sanctions) {\n  console.log(\"OFAC hit:\", result.signer_sanctions.ofac_label, result.signer_sanctions.sdn_uid);\n}\n```\n\nWallet-OFAC SDN enforcement on the `signer` block is unconditional whenever a signer is supplied — no `policy.require_sanctions_clear` opt-in required. The API flips `decision` to `deny` when `signer_sanctions` is `sanctioned: true` OR `status: 'unavailable'`, with `decision_reasons` including `sanctions_flagged` or `sanctions_check_unavailable` respectively (fail-closed; OFAC strict-liability). `policy.require_sanctions_clear` is the separate NAME-based screen on the resolved operator's KYC identity.\n\nPass `signer.address: null` for rails without a wallet signer (Stripe SPT, card-only). The API responds with `signer_match.kind = 'wallet_auth_requires_wallet_signing'` and a parsed `agent_instructions` block telling the agent to switch to `X-Operator-Token` auth — spread the block directly into a 403 body.\n\n### Credential Management\n\n```typescript\nconst cred = await client.createCredential({ label: \"my-agent\", ttl_days: 7 });\nconsole.log(cred.credential); // shown once\n\nconst list = await client.listCredentials();\nconsole.log(list); // active, non-expired credentials\n\nawait client.revokeCredential(cred.id);\n```\n\n### Report an Agent's Wallet (Cross-Merchant Attribution)\n\nAfter an agent authenticated via `operator_token` completes a payment, report the signer wallet so AgentScore can build a cross-merchant credential↔wallet profile. Fire-and-forget — `first_seen` is informational only. `network` is the key-derivation family: `\"evm\"` for any EVM chain (Base, Tempo, Ethereum, …) or `\"solana\"` for Solana.\n\n```typescript\nawait client.associateWallet({\n  operatorToken: \"opc_...\",\n  walletAddress: signerFromPayment, // e.g. EIP-3009 `from` or Tempo MPP DID address\n  network: \"evm\",\n  idempotencyKey: paymentIntentId, // optional — agent retries of the same payment no-op\n});\n```\n\n## Configuration\n\n| Option      | Type     | Default                     | Description              |\n| ----------- | -------- | --------------------------- | ------------------------ |\n| `apiKey`    | `string` | ---                         | API key from [agentscore.sh](https://agentscore.sh) |\n| `baseUrl`   | `string` | `https://api.agentscore.sh` | API base URL             |\n| `timeout`   | `number` | `10000`                     | Request timeout in ms    |\n| `userAgent` | `string` | ---                         | Prepended to the default `User-Agent` as `\"{userAgent} (@agent-score/sdk@{version})\"`. Use to attribute API calls to your app. |\n\n## Error Handling\n\n```typescript\nimport { AgentScore, AgentScoreError } from \"@agent-score/sdk\";\n\ntry {\n  await client.getReputation(\"0xinvalid\");\n} catch (err) {\n  if (err instanceof AgentScoreError) {\n    console.error(err.code, err.message, err.status);\n  }\n}\n```\n\n`AgentScoreError.details` carries the rest of the response body — `verify_url`, `linked_wallets`, `claimed_operator`, `actual_signer`, `expected_signer`, `reasons`, `agent_memory` — so callers can branch on granular denial codes without re-parsing.\n\n### Typed error classes\n\nFor status-code-specific recovery, the SDK throws typed subclasses of `AgentScoreError`. All inherit from `AgentScoreError` so existing `catch (err) { if (err instanceof AgentScoreError) ... }` still works.\n\n| Class | Triggered by | What it adds |\n|---|---|---|\n| `PaymentRequiredError` | HTTP 402 | The endpoint is not enabled for this account |\n| `TokenExpiredError` | HTTP 401 with `error.code = \"token_expired\"` | Parsed body fields exposed on the instance: `verifyUrl`, `sessionId`, `pollSecret`, `pollUrl`, `nextSteps`, `agentMemory` — recover without re-parsing `details` |\n| `InvalidCredentialError` | HTTP 401 with `error.code = \"invalid_credential\"` | Permanent — switch tokens or restart |\n| `QuotaExceededError` | HTTP 429 with `error.code = \"quota_exceeded\"` | Account-level cap reached; don't retry |\n| `RateLimitedError` | HTTP 429 with `error.code = \"rate_limited\"` | Per-second sliding-window cap; retry after `Retry-After` |\n| `TimeoutError` | Request aborted before a response arrived | Distinct from generic network errors |\n\n```typescript\nimport {\n  AgentScore, AgentScoreError, TokenExpiredError, QuotaExceededError, TimeoutError,\n} from \"@agent-score/sdk\";\n\ntry {\n  await client.assess(\"0xabc...\", { policy: { require_kyc: true } });\n} catch (err) {\n  if (err instanceof TokenExpiredError) {\n    console.log(\"Verify at:\", err.verifyUrl, \"poll with:\", err.pollSecret);\n  } else if (err instanceof QuotaExceededError) {\n    console.log(\"Account quota reached — surface to user; don't retry.\");\n  } else if (err instanceof TimeoutError) {\n    console.log(\"Network timeout — retry with backoff.\");\n  } else if (err instanceof AgentScoreError) {\n    console.error(err.code, err.message);\n  }\n}\n```\n\n## Quota observability\n\n`assess()` responses include an optional `quota` field captured from `X-Quota-Limit` / `X-Quota-Used` / `X-Quota-Reset` response headers. Use it to monitor approach-to-cap proactively (warn at 80%, alert at 95%) before a 429:\n\n```typescript\nconst result = await client.assess(\"0xabc...\", { policy: { require_kyc: true } });\nif (result.quota \u0026\u0026 result.quota.limit \u0026\u0026 result.quota.used) {\n  const pct = (result.quota.used / result.quota.limit) * 100;\n  if (pct \u003e 80) console.warn(`AgentScore quota at ${pct.toFixed(1)}% — resets ${result.quota.reset}`);\n}\n```\n\n`quota` is `undefined` when the API doesn't emit the headers (Enterprise / unlimited tiers). On a 429 response the SDK throws `QuotaExceededError` / `RateLimitedError` instead of returning a body, so `quota` is only readable on successful calls — drive proactive alerting off the success-path field.\n\n## Telemetry\n\n`telemetrySignerMatch(payload)` is a fire-and-forget POST to `/v1/telemetry/signer-match` so AgentScore can track aggregate signer-binding behavior across merchants. Used internally by `@agent-score/commerce`'s gate; available directly for custom integrations that perform their own wallet-signer-match checks.\n\n## Documentation\n\n- [API Reference](https://docs.agentscore.sh)\n\n## License\n\n[MIT](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fagentscore%2Fnode-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fagentscore%2Fnode-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fagentscore%2Fnode-sdk/lists"}