Geofencing API
Create virtual boundaries and receive notifications when devices enter or exit.
Create virtual boundaries around locations and get notified when your AirTags cross them. Notifications are throttled to once per 30 minutes per device.
Endpoints
List Geofences
Retrieve a list of all geofences configured for your AirTags.
Endpoint
GET /v1/geofences
Query Parameters
skip: Number of items to skip (for pagination, default: 0)limit: Maximum number of items to return (1-100, default: 20)trackable_id: Optional ID to filter geofences for a specific AirTag
Example Request
curl -X GET "https://api.airpinpoint.com/v1/geofences?limit=20&trackable_id=tag_123456" \
-H "Authorization: Bearer YOUR_API_KEY"Example Response
[
{
"id": "geofence_789012",
"name": "Home",
"authUserId": "user_123",
"latitude": 37.7749,
"longitude": -122.4194,
"radius": 100,
"createdAt": "2023-06-15T17:00:00Z",
"updatedAt": "2023-06-15T17:00:00Z",
"trackableId": ["tag_123456", "tag_789012"],
}
]Create a Geofence for AirTags
Create a new geofence for multiple AirTags or other trackable devices of the same type.
Endpoint
POST /v1/geofences
Request Body
{
name: string; // Descriptive name for the geofence
latitude: number; // Center latitude of the geofence
longitude: number; // Center longitude of the geofence
radius: number; // Radius in meters (10-5000)
trackableId: string[]; // Array of AirTag IDs to monitor
notifyType?: string; // Optional: "enter", "exit", "both", or "webhook"
notifyDestination?: string; // Optional: Email or webhook URL for notifications
webhookSecret?: string; // Optional: Secret for webhook signature verification
webhookEnabled?: boolean; // Optional: Enable/disable webhook delivery
webhookHeaders?: object; // Optional: Custom headers for webhook requests
}Example Request
curl -X POST "https://api.airpinpoint.com/v1/geofences" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Warehouse Zone A",
"latitude": 37.7749,
"longitude": -122.4194,
"radius": 100,
"trackableId": ["tag_123456", "tag_789012"],
"notifyType": "both",
"notifyDestination": "https://yourapp.com/webhooks/geofence",
"webhookSecret": "your_secret_key",
"webhookEnabled": true
}'Example Response
{
"id": "geofence_789012",
"name": "Warehouse Zone A",
"authUserId": "user_123",
"latitude": 37.7749,
"longitude": -122.4194,
"radius": 100,
"createdAt": "2023-06-15T17:00:00Z",
"updatedAt": "2023-06-15T17:00:00Z",
"trackableId": ["tag_123456", "tag_789012"],
"notifyType": "both",
"notifyDestination": "https://yourapp.com/webhooks/geofence",
"webhookEnabled": true
}Delete a Geofence
Remove a geofence when it's no longer needed.
Endpoint
DELETE /v1/geofences/{geofence_id}
Example Request
curl -X DELETE "https://api.airpinpoint.com/v1/geofences/geofence_789012" \
-H "Authorization: Bearer YOUR_API_KEY"Example Response
{
"message": "Geofence deleted successfully"
}Update a Geofence
Update an existing geofence, including webhook configuration.
Endpoint
PATCH /v1/geofences/{geofence_id}
Request Body
{
name?: string; // Optional: New name for the geofence
latitude?: number; // Optional: New center latitude
longitude?: number; // Optional: New center longitude
radius?: number; // Optional: New radius in meters (10-5000)
trackableId?: string[]; // Optional: New array of AirTag IDs to monitor
notifyType?: string; // Optional: "enter", "exit", "both", or "webhook"
notifyDestination?: string; // Optional: New email or webhook URL
webhookSecret?: string; // Optional: New webhook secret
webhookEnabled?: boolean; // Optional: Enable/disable webhook delivery
webhookHeaders?: object; // Optional: Custom headers for webhook requests
}Example Request
curl -X PATCH "https://api.airpinpoint.com/v1/geofences/geofence_789012" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Updated Warehouse Zone",
"notifyType": "webhook",
"notifyDestination": "https://yourapp.com/new-webhook-endpoint",
"webhookSecret": "your_secret_key",
"webhookEnabled": true
}'Example Response
{
"id": "geofence_789012",
"name": "Updated Warehouse Zone",
"authUserId": "user_123",
"latitude": 37.7749,
"longitude": -122.4194,
"radius": 100,
"createdAt": "2023-06-15T17:00:00Z",
"updatedAt": "2023-06-16T10:30:00Z",
"trackableId": ["tag_123456", "tag_789012"],
"notifyType": "webhook",
"notifyDestination": "https://yourapp.com/new-webhook-endpoint",
"webhookEnabled": true
}Test a Webhook
Send a test webhook delivery to verify your webhook configuration.
Endpoint
POST /v1/geofences/{geofence_id}/test-webhook
Request Body
{
eventType: string; // "entry" or "exit"
}Example Request
curl -X POST "https://api.airpinpoint.com/v1/geofences/geofence_789012/test-webhook" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"eventType": "entry"
}'Example Response
{
"success": true,
"message": "Test webhook successfully sent for entry event",
"deliveryId": "webhook_delivery_123456"
}Geofence Notification Webhooks
When an AirTag enters or exits a geofence, AirPinpoint can send a webhook notification to your application. This enables real-time reactions to location changes.
Webhook Configuration
To set up webhook notifications for your geofence:
- When creating or updating a geofence, set
notifyTypeto"webhook" - Provide a publicly accessible HTTPS endpoint as
notifyDestination - Optionally, set a
webhookSecretfor added security - Set
webhookEnabledtotrueto activate webhook delivery
Testing Your Webhook
You can test your webhook configuration before deploying:
curl -X POST "https://api.airpinpoint.com/v1/geofences/{geofence_id}/test-webhook" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"eventType": "entry"
}'This will send a test payload to your webhook endpoint and return information about the delivery attempt.
Webhook Payload Format
{
"event": "geofence.entry", // or "geofence.exit"
"occurred_at": "2023-06-15T17:30:00Z",
"geofence": {
"id": "geofence_789012",
"name": "Warehouse Zone A",
"latitude": 37.7749,
"longitude": -122.4194,
"radius": 100
},
"beacon": {
"id": "tag_123456",
"name": "Forklift #3",
"type": "apple"
},
"location": {
"latitude": 37.7752,
"longitude": -122.4192,
"accuracy": 10,
"timestamp": "2023-06-15T17:30:00Z"
}
}Webhook Security
For enhanced security, set a webhook secret when configuring your geofence. The webhook request will include an X-AirPinpoint-Signature header with an HMAC-SHA256 signature of the payload, using your secret as the key.
Verify this signature in your webhook handler:
const crypto = require('crypto');
// In your webhook handler
function verifyWebhookSignature(payload, signature, secret) {
const computedSignature = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(computedSignature)
);
}
app.post('/webhooks/geofence', (req, res) => {
const signature = req.headers['x-airpinpoint-signature'];
const isValid = verifyWebhookSignature(req.body, signature, 'your_webhook_secret');
if (!isValid) {
return res.status(403).send('Invalid signature');
}
// Process the webhook...
res.status(200).send('Webhook received');
});Setting Up Webhook Handlers
Create an endpoint in your application to receive these notifications:
// Example Express.js webhook handler
app.post('/webhooks/geofence', (req, res) => {
// Verify signature if using webhook secrets
const signature = req.headers['x-airpinpoint-signature'];
if (signature) {
const isValid = verifyWebhookSignature(req.body, signature, 'your_webhook_secret');
if (!isValid) {
return res.status(403).send('Invalid signature');
}
}
const { event, geofence, beacon, occurred_at } = req.body;
console.log(`${beacon.name} ${event === 'geofence.entry' ? 'entered' : 'exited'} ${geofence.name} at ${occurred_at}`);
// Trigger your business logic here
if (event === 'geofence.entry') {
// Handle entry event
notifyWarehouseManager(beacon.name, geofence.name);
} else if (event === 'geofence.exit') {
// Handle exit event
logDeviceExit(beacon.name, geofence.name, occurred_at);
}
res.status(200).send('Webhook received');
});Limitations
- Geofences require a minimum radius of 10 meters
- Maximum radius is limited to 5000 meters (5 km)
- All trackables in a geofence must be of the same type (airtag, device, or beacon)
- A trackable must have location data available before it can be added to a geofence
- Each account has a default limit of 100 geofences (contact support for higher limits)
- Multiple trackables can be added to a single geofence
- Webhooks must use HTTPS for security reasons
- Webhook timeouts are set to 10 seconds; ensure your endpoint responds quickly