...

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:

  1. When creating or updating a geofence, set notifyType to "webhook"
  2. Provide a publicly accessible HTTPS endpoint as notifyDestination
  3. Optionally, set a webhookSecret for added security
  4. Set webhookEnabled to true to 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