Agent SDK quickstart

Register an agent, sign a payment intent, watch it authorize against Visa. Three implementations: TypeScript, Python, curl + openssl.

TypeScript

Installbash
npm install @sorenpay/agent-sdk
quickstart.tstypescript
import { SorenAgent } from "@sorenpay/agent-sdk";

const soren = new SorenAgent({
apiKey: process.env.SOREN_API_KEY!, // apk_…
});

// 1. Register (generates Ed25519 keypair locally; returns the private key ONCE)
const { agent, privateKeyPem } = await soren.register({
agentName: "research-assistant",
protocols: ["TAP", "MPP", "ACP"],
});
// → persist privateKeyPem to your secret store

// 2. Sign + submit a payment intent
const result = await soren.submitIntent({
agentId: agent.id,
privateKeyPem,
merchant: { name: "OpenAI API", mcc: "5734" },
amount: { currency: "USD", cents: 1500 },
protocol: "TAP",
ttlSeconds: 300,
});

console.log(result.decision, result.reason);
// → APPROVE within_limits

Python

Installbash
pip install sorenpay-agent-sdk
quickstart.pypython
import os
from sorenpay_agent import SorenAgent

soren = SorenAgent(api_key=os.environ["SOREN_API_KEY"])

# 1. Register (generates Ed25519 locally)
register = soren.register(
  agent_name="research-assistant",
  protocols=["TAP", "MPP", "ACP"],
)
# → persist register.private_key_pem to your secret store

# 2. Sign + submit
result = soren.submit_intent(
  agent_id=register.agent.id,
  private_key_pem=register.private_key_pem,
  merchant={"name": "OpenAI API", "mcc": "5734"},
  amount={"currency": "USD", "cents": 1500},
  protocol="TAP",
  ttl_seconds=300,
)

print(result.decision, result.reason)

curl + openssl (zero deps)

Generate Ed25519 keypairbash
openssl genpkey -algorithm Ed25519 -out agent.key
openssl pkey -in agent.key -pubout -out agent.pub
Register the agentbash
PUBKEY=$(cat agent.pub | tr -d '\n')
curl -X POST https://api.sorenpay.com/api/agents \
-H "Authorization: Bearer $SOREN_API_KEY" \
-H "Content-Type: application/json" \
-d "{
  \"agentName\": \"research-assistant\",
  \"protocols\": [\"TAP\", \"MPP\", \"ACP\"],
  \"publicKeyPem\": \"$PUBKEY\"
}"

Signing the canonical JSON is the fiddly part — use one of the SDKs unless you have to. The signing step requires:

  1. Sort all keys recursively
  2. Strip whitespace
  3. Sign with Ed25519 one-shot (crypto.sign(null, …) in Node)
  4. Base64url-encode the signature

Error codes

| HTTP | Code | What | |---|---|---| | 401 | signature_invalid | Signature doesn't match the registered public key | | 401 | intent_expired | intent.exp is in the past | | 422 | intent_id_replay | Duplicate intent_id | | 409 | kyb_required | Live mode + workspace KYB not approved | | 429 | rate-limited | 100 requests/minute default |

Next