Enriched Agentic Webhooks
Traditional webhooks are purely passive notifications—they send a lightweight payload containing nothing more than an ID and a status (e.g. {"assetId": "as_123", "status": "completed"}). For AI agents operating in autonomous frameworks like LangGraph, AutoGen, or CrewAI, this passive approach forces the agent to make multiple sequential API round-trips to pull technical metadata, visual tags, textual summaries, and vector embeddings.
Picsha AI solves this bottleneck with Enriched Agentic Webhooks. When an ingestion pipeline completes, Picsha constructs and dispatches a fully enriched cognitive package containing geocoded location strings, technical details, raw EXIF metadata, AI safety moderation labels (if moderation is enabled), Claude-generated visual summaries, and 1024-dimensional vector embeddings directly to your agent's receiver endpoint.
This enables downstream AI agents to reactively reason over visual and auditory media assets with zero subsequent API round-trips.
1. Supported Webhook Events
Picsha AI triggers webhooks based on the asset lifecycle. You can subscribe to one or more of the following event types:
| Event Type | Trigger Condition |
|---|---|
asset.queued | A new asset has been successfully saved to S3 and is waiting for a Queue Worker. |
asset.active | The worker node has picked up the asset and begun the AI ingestion pipeline. |
asset.processed | All AI analysis, transcription, and multimodal embeddings have completed successfully. |
asset.failed | An unrecoverable error occurred during the ingestion pipeline. |
asset.infected | The ClamAV sidecar detected malware or a virus; the asset is quarantined. |
asset.pending_moderation | AWS Rekognition flagged the asset for unsafe content pending manual review. |
asset.rejected | The asset was manually rejected during moderation review. |
2. Selective Enrichment Configuration
To protect client network bandwidth, safeguard user privacy, and prevent serverless gateway payload failures (e.g. AWS API Gateway limits), Picsha implements a Selective Enrichment architecture.
By default, outgoing webhooks include technical specifications, geocoding, visual tags, and Claude summaries. Developers can explicitly toggle the inclusion of large text blocks and float32 vector arrays during webhook registration:
| Configuration Flag | Type | Default | Description |
|---|---|---|---|
include_embeddings | boolean | false | When enabled, attaches the raw 1024-dimensional Titan Multimodal embedding float array directly to the payload (data.embedding). |
include_text | boolean | false | When enabled, attaches untruncated visual summaries. When disabled, the long summary is truncated to 500 characters. Note: Extracted OCR and transcript data are bound by a hard safety ceiling of 10,000 characters to prevent endpoint timeouts. |
3. Registering a Webhook
You can register a webhook programmatically via our Fastify API gateway. If you register a webhook without providing a custom secret, Picsha automatically generates a cryptographically secure signing secret prefixed with wh_sec_.
Endpoint
POST /v1/webhooks
Request Headers
Authorization: Bearer sk_live_your_key
x-external-user-id: usr_dev_456
Content-Type: application/json
Request Body
{
"url": "https://api.yourdomain.com/agents/media-receiver",
"events": ["asset.processed"],
"config": {
"include_embeddings": true,
"include_text": true
}
}
Response
{
"id": 42,
"url": "https://api.yourdomain.com/agents/media-receiver",
"events": ["asset.processed"],
"secret": "wh_sec_d83e1c9f824a73b9d0e1f2a3b4c5d6e7f8",
"config": {
"include_embeddings": true,
"include_text": true
}
}
[!IMPORTANT] Write down your generated signing
secretwhen you receive the creation response. For security reasons, the secret is only returned in full upon registration and cannot be retrieved later in plaintext.
4. Cognitive Payload Structure
Below is an example of a fully enriched asset.processed event payload delivered to a client receiver when both include_embeddings and include_text are enabled:
{
"event": "asset.processed",
"timestamp": "2026-06-02T03:00:00.000Z",
"data": {
"assetId": "123e4567-e89b-12d3-a456-426614174000",
"orgId": "org_default",
"userId": "usr_dev_456",
"originalName": "cambridge_meeting.jpg",
"mimeType": "image/jpeg",
"size": 2451092,
"width": 4032,
"height": 3024,
"captureDate": "2026-05-24T18:45:00.000Z",
"cameraMake": "Apple",
"cameraModel": "iPhone 15 Pro",
"status": "completed",
"fileHash": "sha256_b2c4d6...",
"url": "https://cdn.picsha.ai/usr_dev_456/123e4567-e89b-12d3-a456-426614174000/source.jpg",
"tags": ["meeting", "indoors", "whiteboard", "laptop", "office"],
"locationString": "Cambridge, MA, USA",
"hlsStream": null,
"aiAnalysis": {
"summaryShort": "A team meeting in a well-lit office space with whiteboards.",
"summaryLong": "A detailed shot of a collaborative workspace in Cambridge. There are three individuals seated around a conference table looking at a laptop. The background features a glass whiteboard covered with architectural diagrams and flowchart structures. Lighting is bright and even, indicating daytime office work.",
"truncated": false
},
"rawExif": {
"FocalLength": "6.86 mm",
"FNumber": 1.78,
"ExposureTime": "1/60",
"ISO": 80
},
"embedding": [
-0.012495,
0.048291,
-0.082491,
0.001924,
0.081726
// ... 1024-float32 vector elements
],
"createdAt": "2026-06-02T02:58:00.000Z",
"updatedAt": "2026-06-02T02:59:30.000Z",
"cost": "$0.0250"
}
}
5. Secure Signature Verification
To guarantee that incoming webhook payloads originate exclusively from Picsha AI, each tailored payload is cryptographically signed before dispatch using the webhook’s distinct secret.
Picsha attaches the following headers to each outgoing POST request:
X-Picsha-Event: The event type (e.g.asset.processed).X-Picsha-Signature: The computed HMAC SHA-256 signature of the raw request body.
Node.js / TypeScript Verification Example
Below is a standard Express or Fastify middleware code snippet to securely verify the signature on your receiving backend:
import crypto from 'crypto';
import express from 'express';
const app = express();
function verifyPicshaSignature(
secret: string,
signature: string,
rawBody: Buffer
): boolean {
const computed = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature, 'hex'),
Buffer.from(computed, 'hex')
);
}
// Usage inside an Express Route:
// IMPORTANT: You must use express.raw() to capture the exact raw bytes sent by Picsha
app.post(
'/webhooks/picsha',
express.raw({ type: 'application/json' }),
(req, res) => {
const signature = req.headers['x-picsha-signature'] as string;
const secret = process.env.PICSHA_WEBHOOK_SECRET!; // Your wh_sec_... key
if (!signature) {
return res.status(401).send('Missing signature header');
}
// Verify using the raw buffer, NOT a parsed JSON object
const isValid = verifyPicshaSignature(secret, signature, req.body);
if (!isValid) {
return res.status(403).send('Invalid signature verification');
}
// Now that it's verified, we can safely parse the JSON payload
const payload = JSON.parse(req.body.toString('utf8'));
const { assetId, aiAnalysis, embedding } = payload.data;
console.log(`Received secure update for asset: ${assetId}`);
res.status(200).send({ received: true });
}
);
Python Verification Example
Below is a standard Python / Flask implementation to verify the payload signature using the raw request bytes:
import hmac
import hashlib
import json
from flask import Flask, request, abort
app = Flask(__name__)
def verify_signature(secret: str, signature: str, raw_body: bytes) -> bool:
computed = hmac.new(
secret.encode('utf-8'),
raw_body,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, computed)
@app.route('/webhooks/picsha', methods=['POST'])
def picsha_webhook():
signature = request.headers.get('X-Picsha-Signature')
secret = "wh_sec_your_key_here"
if not signature:
abort(401, description="Missing signature header")
# Verify using the raw bytes, NOT the parsed JSON dictionary
raw_body = request.get_data()
if not verify_signature(secret, signature, raw_body):
abort(403, description="Invalid cryptographic signature")
# Signature is valid. Parse and hand off the data block directly to your AI agent!
payload = request.get_json()
data_block = payload.get('data', {})
data = payload['data']
print(f"Verified secure cognitive package for asset: {data['assetId']}")
return {"status": "success"}, 200
6. Webhooks Feature Comparison
The table below contrasts Picsha AI's Enriched Agentic Webhooks with major competitors—Cloudinary, Uploadcare, and Bytescale:
| Feature / Payload Data | Cloudinary | Uploadcare | Bytescale | Picsha AI (Agentic) |
|---|---|---|---|---|
| Technical Metadata (Size, Mime, Dims) | Yes | Yes | Yes | Yes |
Basic Text Tags (e.g., ["car"]) | Yes | No | No | Yes |
| HMAC Security Signatures | Yes | Yes | No | Yes |
| Antivirus Scan Status | No | Yes | No | Yes ($1.00 / 1k scans) |
| Claude Visual Summary (Visual Context) | No | No | No | Yes (Enriched) |
| Document OCR Text Extract | No | No | No | Yes (Enriched) |
| A/V Speech-to-Text Transcripts | No | No | No | Yes (Enriched) |
| Geocoded Location Strings | No | No | No | Yes (Enriched) |
| Multimodal Vector Embedding (1024d) | No | No | No | Yes (Enriched) |
By combining cryptographically secure delivery, multi-tenant safety boundaries, and highly customized cognitive summaries, Picsha AI's Enriched Agentic Webhooks establish the premier standard for building high-performance, event-driven media intelligence systems.