GraphQL API - Webhooks
Webhooks provide real-time notifications for order status updates in your Layer One platform. Track the order’s progress by either registering a webhook for asynchronous updates or querying for order details directly.
Webhook Schema
type Webhook {
webhook_id: ID!
created: DateTime!
webhook_url: String!
webhook_events: [String!]!
}
enum WebhookEvent {
ORDER_UPDATED
}
type WebhookEvent {
event: String!
timestamp: DateTime!
order: OrderEventData!
}
type OrderEventData {
order_id: ID!
order_status: String!
failure_reason: String
metadata: String
}
Queries
Get All Webhooks
Lists all webhooks created by App (limited to 1). App has two ways of requesting the order status: querying for order details or via a webhook event.
query {
webhooks {
webhook_id
created
webhook_url
webhook_events
}
}
Response:
{
"data": {
"webhooks": [
{
"webhook_id": "244d8058-035b-422d-821f-44eedbaa42a4",
"created": "2025-06-05T06:43:04.000Z",
"webhook_url": "https://local-api.integrated-projects.com/v1/webhooks/test",
"webhook_events": [
"order.updated"
]
}
]
}
}
Mutations
Create Webhook
Track the order’s progress by registering a webhook for asynchronous updates.
mutation CreateWebhook($webhook_url: String!) {
createWebhook(webhook_url: $webhook_url) {
webhook_id
created
webhook_url
webhook_events
}
}
Variables:
{
"webhook_url": "https://local-api.integrated-projects.com/v1/webhooks/test"
}
Response:
{
"data": {
"createWebhook": {
"webhook_id": "244d8058-035b-422d-821f-44eedbaa42a4",
"created": "2025-06-05T06:43:04.000Z",
"webhook_url": "https://local-api.integrated-projects.com/v1/webhooks/test",
"webhook_events": [
"order.updated"
]
}
}
}
Parameters
Parameter | Type | Description | Required |
---|---|---|---|
webhook_url | String | Supplied Webhook URL to receive order updates | ✓ |
Response Fields:
Field | Type | Description |
---|---|---|
webhook_id | ID | Webhook identifier |
created | DateTime | Time webhook was created |
webhook_url | String | Supplied Webhook URL to receive order updates |
webhook_events | Array | Only order.updated supported |
Update Webhook
Update an existing webhook’s URL or configuration.
mutation UpdateWebhook(
$webhook_id: ID!
$webhook_url: String!
) {
updateWebhook(
webhook_id: $webhook_id
webhook_url: $webhook_url
) {
webhook_id
created
webhook_url
webhook_events
}
}
Variables:
{
"webhook_id": "244d8058-035b-422d-821f-44eedbaa42a4",
"webhook_url": "https://local-api.integrated-projects.com/v1/webhooks/test"
}
Response:
{
"data": {
"updateWebhook": {
"webhook_id": "244d8058-035b-422d-821f-44eedbaa42a4",
"created": "2025-06-05T06:43:04.000Z",
"webhook_url": "https://local-api.integrated-projects.com/v1/webhooks/test",
"webhook_events": [
"order.updated"
]
}
}
}
Delete Webhook
Remove an existing webhook.
mutation DeleteWebhook($webhook_id: ID!) {
deleteWebhook(webhook_id: $webhook_id) {
webhook_id
created
webhook_url
webhook_events
}
}
Variables:
{
"webhook_id": "244d8058-035b-422d-821f-44eedbaa42a4"
}
Response:
{
"data": {
"deleteWebhook": {
"webhook_id": "244d8058-035b-422d-821f-44eedbaa42a4",
"created": "2025-06-05T06:43:04.000Z",
"webhook_url": "https://local-api.integrated-projects.com/v1/webhooks/test",
"webhook_events": [
"order.updated"
]
}
}
}
Parameters
Parameter | Type | Description | Required |
---|---|---|---|
webhook_id | ID | Webhook identifier | ✓ |
webhook_url | String | Supplied Webhook URL to receive order updates | ✓ (update only) |
Webhook Event Examples
When order status changes occur, your webhook URL will receive HTTP POST requests with order update information.
Order Failed Event
{
"event": "order.updated",
"timestamp": "2025-06-04T18:15:30Z",
"order": {
"order_id": "123",
"order_status": "Order Failed",
"failure_reason": "Point cloud processing error",
"metadata": "{\"project_id\":\"123\"}"
}
}
Order Completed Event
{
"event": "order.updated",
"timestamp": "2025-06-04T18:15:30Z",
"order": {
"order_id": "123",
"order_status": "Order Completed",
"metadata": "{\"project_id\":\"123\"}"
}
}
Webhook Implementation
Endpoint Setup
Your webhook endpoint should:
- Accept HTTP POST requests
- Respond with HTTP 200 status for successful delivery
- Handle the
order.updated
event type - Process order status changes asynchronously
Example Implementation
// Express.js webhook handler
app.post('/webhooks/order-updates', (req, res) => {
const { event, timestamp, order } = req.body;
if (event === 'order.updated') {
console.log(`Order ${order.order_id} status: ${order.order_status}`);
switch (order.order_status) {
case 'Order Processing':
handleOrderProcessing(order.order_id);
break;
case 'Order Completed':
handleOrderCompleted(order.order_id);
break;
case 'Order Failed':
handleOrderFailed(order.order_id, order.failure_reason);
break;
}
}
res.status(200).send('OK');
});
const handleOrderCompleted = (orderId: string) => {
console.log(`Order ${orderId} completed successfully`);
// Download results, notify user, update database, etc.
};
const handleOrderFailed = (orderId: string, reason: string) => {
console.log(`Order ${orderId} failed: ${reason}`);
// Notify user, log error, retry logic, etc.
};
Complete Webhook Workflow
Step-by-Step Integration
// 1. Create a webhook
const createWebhookMutation = `
mutation CreateWebhook($webhook_url: String!) {
createWebhook(webhook_url: $webhook_url) {
webhook_id
webhook_url
webhook_events
created
}
}
`;
const webhookResponse = await graphqlClient.request(createWebhookMutation, {
webhook_url: "https://your-app.com/webhooks/order-updates"
});
console.log("Webhook created:", webhookResponse.createWebhook.webhook_id);
// 2. Query existing webhooks
const queryWebhooksQuery = `
query {
webhooks {
webhook_id
webhook_url
webhook_events
created
}
}
`;
const webhooksResponse = await graphqlClient.request(queryWebhooksQuery);
console.log("Active webhooks:", webhooksResponse.webhooks);
// 3. Update webhook if needed
const updateWebhookMutation = `
mutation UpdateWebhook($webhook_id: ID!, $webhook_url: String!) {
updateWebhook(webhook_id: $webhook_id, webhook_url: $webhook_url) {
webhook_id
webhook_url
webhook_events
}
}
`;
// 4. Delete webhook when no longer needed
const deleteWebhookMutation = `
mutation DeleteWebhook($webhook_id: ID!) {
deleteWebhook(webhook_id: $webhook_id) {
webhook_id
}
}
`;
Error Handling
Common Webhook Errors
{
"errors": [
{
"message": "Invalid webhook URL",
"extensions": {
"code": "INVALID_WEBHOOK_URL",
"url": "invalid-url"
}
},
{
"message": "Webhook not found",
"extensions": {
"code": "WEBHOOK_NOT_FOUND",
"webhook_id": "invalid-webhook-id"
}
}
]
}
Error Codes
INVALID_WEBHOOK_URL
- Malformed or unreachable webhook URLWEBHOOK_NOT_FOUND
- Webhook does not existWEBHOOK_LIMIT_EXCEEDED
- App limited to 1 webhookWEBHOOK_DELIVERY_FAILED
- Failed to deliver webhook event
Best Practices
Webhook Endpoint Requirements
- HTTPS Only - Webhook URLs must use HTTPS
- Fast Response - Respond with HTTP 200 within 30 seconds
- Idempotency - Handle duplicate deliveries gracefully
- Error Handling - Log and handle webhook processing errors
URL Validation
const isValidWebhookUrl = (url: string): boolean => {
try {
const parsedUrl = new URL(url);
return parsedUrl.protocol === 'https:' &&
parsedUrl.hostname !== 'localhost' &&
!parsedUrl.hostname.startsWith('127.');
} catch {
return false;
}
};
Webhook Reliability
// Implement idempotency
const processedEvents = new Set();
app.post('/webhooks/order-updates', (req, res) => {
const { event, timestamp, order } = req.body;
const eventId = `${event}-${timestamp}-${order.order_id}`;
if (processedEvents.has(eventId)) {
console.log('Duplicate event, skipping');
return res.status(200).send('OK');
}
try {
// Process the event
processOrderUpdate(order);
processedEvents.add(eventId);
res.status(200).send('OK');
} catch (error) {
console.error('Webhook processing failed:', error);
res.status(500).send('Processing failed');
}
});
Order Status Tracking
Status Flow
Order webhooks will notify you of these status changes:
- Order Initialized - Order created successfully
- Order Processing - Order submitted and being processed
- Order Completed - Processing finished successfully
- Order Failed - Processing encountered an error
Event Monitoring
interface OrderStatusHandler {
onInitialized: (orderId: string) => void;
onProcessing: (orderId: string) => void;
onCompleted: (orderId: string) => void;
onFailed: (orderId: string, reason: string) => void;
}
const handleWebhookEvent = (payload: any, handlers: OrderStatusHandler) => {
const { order } = payload;
switch (order.order_status) {
case 'Order Initialized':
handlers.onInitialized(order.order_id);
break;
case 'Order Processing':
handlers.onProcessing(order.order_id);
break;
case 'Order Completed':
handlers.onCompleted(order.order_id);
break;
case 'Order Failed':
handlers.onFailed(order.order_id, order.failure_reason);
break;
}
};
Webhook Limitations
- Limit: App is limited to 1 webhook registration
- Events: Only
order.updated
events are supported - Delivery: No automatic retry mechanism - ensure endpoint reliability
- Timeout: Webhook requests timeout after 30 seconds