Using the SDK
@agentpress/sdk is the official TypeScript SDK for interacting with the AgentPress webhook system. It handles HMAC-SHA256 signing, payload construction, and signature verification with zero runtime dependencies (uses only node:crypto). Dual ESM and CommonJS output, requires Node 22 or later.
Installation
npm install @agentpress/sdk
# or
bun add @agentpress/sdkClient Setup
Create an AgentPress client instance with your webhook secret and organization slug:
import { AgentPress } from "@agentpress/sdk";
const client = new AgentPress({
webhookSecret: "whsec_your_secret_here",
org: "your-org-slug",
baseUrl: "https://api.agent.press",
});Options
| Option | Type | Default | Description |
|---|---|---|---|
webhookSecret | string | — | Svix signing secret (must start with whsec_). Required for send and verify operations. |
org | string | "default-org" | Organization slug used in the webhook URL path. |
baseUrl | string | "https://api.agent.press" | API base URL. Trailing slashes are stripped automatically. |
timeout | number | 30000 | Request timeout in milliseconds. Must be a positive finite number. |
apiKey | string | — | API key for authenticated requests (reserved for future use). |
onRequest | (url: string, init: RequestInit) => void | — | Hook called before every outbound HTTP request. Useful for logging or tracing. |
onResponse | (url: string, response: Response) => void | — | Hook called after every HTTP response is received. |
The client validates all options at construction time. A webhookSecret that does not start with whsec_ or a non-positive timeout will throw a ConfigurationError immediately.
Sending Events
Basic Events
Use client.webhooks.send() to sign and send an arbitrary webhook payload to AgentPress:
const response = await client.webhooks.send({
action: "my_webhook_action",
payload: {
eventType: "order.completed",
externalId: "order-456",
data: { total: 99.99 },
},
});This sends a POST request to {baseUrl}/webhooks/actions/{org}/{action}.
The SDK handles the full Svix signing flow automatically:
- Generates a unique message ID (
msg_<uuid>) for thesvix-idheader - Creates a Unix timestamp for the
svix-timestampheader - Signs the payload with HMAC-SHA256 using your webhook secret
- Sends the JSON body with all three Svix headers attached
Response
The send() method returns a WebhookResponse:
| Field | Type | Description |
|---|---|---|
success | boolean | Whether the action was created successfully. |
actionId | string? | UUID of the created action. |
alreadyExists | boolean? | true if a duplicate externalId was detected (idempotency). |
skipped | boolean? | true if no matching action rule is configured for this webhook. |
Review Events
client.webhooks.sendReviewAction() is a high-level method for sending review events. It handles star rating normalization and instruction templating:
const response = await client.webhooks.sendReviewAction({
externalId: "review-123",
authProvider: "google_business",
review: {
eventType: "review.created",
rating: "FOUR",
text: "Good experience overall.",
reviewer: "Jane Smith",
locationName: "Downtown Office",
createTime: new Date().toISOString(),
updateTime: null,
},
instructions: { tone: "empathetic and solution-oriented" },
});Star Rating Normalization
The rating field accepts multiple formats and normalizes them to a numeric value before sending:
| Input | Output | Notes |
|---|---|---|
null | null | No rating provided. |
5 | 5 | Numeric values pass through unchanged. |
"FIVE" | 5 | Google Business Profile StarRating enum. |
"5" | 5 | Numeric strings are parsed. |
"STAR_RATING_UNSPECIFIED" | null | Google unspecified value. |
"invalid" | throws | Unrecognized strings throw an AgentPressError. |
Instruction Modes
The instructions parameter supports two forms:
- Tone-based —
{ tone: "friendly" }wraps the tone value in a structured template with prompt injection protection. The template provides base instructions for review response generation. - Raw —
{ raw: "Respond in Spanish." }passes the string directly as instructions with no wrapping or transformation.
Verifying Inbound Webhooks
When AgentPress sends callbacks to your server (e.g., after an action completes), use the verification methods to validate the Svix signature.
verify
Returns a boolean indicating whether the signature is valid:
const isValid = client.webhooks.verify({
payload: rawRequestBody,
headers: {
"svix-id": req.headers["svix-id"],
"svix-timestamp": req.headers["svix-timestamp"],
"svix-signature": req.headers["svix-signature"],
},
});
if (!isValid) {
return res.status(401).json({ error: "Invalid signature" });
}verifyOrThrow
Throws a WebhookSignatureError on invalid or expired signatures. Useful in middleware patterns:
try {
client.webhooks.verifyOrThrow({
payload: rawRequestBody,
headers: {
"svix-id": req.headers["svix-id"],
"svix-timestamp": req.headers["svix-timestamp"],
"svix-signature": req.headers["svix-signature"],
},
});
} catch (error) {
return res.status(401).json({ error: "Invalid signature" });
}constructEvent
Combines signature verification with JSON parsing. This is the recommended method for handling inbound webhooks:
import type { ActionCallbackPayload } from "@agentpress/sdk";
const event: ActionCallbackPayload = client.webhooks.constructEvent({
payload: rawRequestBody,
headers: {
"svix-id": req.headers["svix-id"],
"svix-timestamp": req.headers["svix-timestamp"],
"svix-signature": req.headers["svix-signature"],
},
});
console.log(`Action ${event.actionId} completed with status: ${event.status}`);Throws WebhookSignatureError if the signature is invalid, or AgentPressError if the payload is not valid JSON.
Signatures expire after 5 minutes. Requests with a svix-timestamp older than that are rejected.
For full details on callback payload structure and setup, see Receiving Callbacks.
Error Handling
The SDK uses a typed error hierarchy. All errors extend AgentPressError, so you can catch broadly or handle specific error types:
AgentPressError (base)
├── ConfigurationError — invalid options or missing webhookSecret
├── HttpError — non-2xx response (has statusCode, responseBody, url)
├── TimeoutError — request exceeded configured timeout
└── WebhookSignatureError — invalid or expired signatureExample
import {
AgentPress,
AgentPressError,
ConfigurationError,
HttpError,
TimeoutError,
} from "@agentpress/sdk";
try {
await client.webhooks.send({ action: "test", payload: {} });
} catch (error) {
if (error instanceof HttpError) {
console.error(`HTTP ${error.statusCode}: ${error.responseBody}`);
console.error(`URL: ${error.url}`);
} else if (error instanceof TimeoutError) {
console.error("Request timed out");
} else if (error instanceof ConfigurationError) {
console.error("Invalid configuration:", error.message);
} else if (error instanceof AgentPressError) {
console.error("SDK error:", error.message);
}
}Exported Types
All types are exported from the package root for use in your application code:
import type {
ActionCallbackPayload,
ActionStatus,
AgentPressOptions,
AgentResponse,
GoogleStarRating,
ReviewActionParams,
ToolCallResult,
WebhookResponse,
WebhookSendParams,
WebhookVerifyParams,
} from "@agentpress/sdk";The ActionCallbackPayload, AgentResponse, and ToolCallResult types are covered in detail in Receiving Callbacks.