Location tracking (FindMy)
How to track the real-time location of contacts who share their location via Apple FindMy
This guide covers using the Location API to access FindMy friend locations available through your blooio account. You can list all contacts sharing their location, fetch a specific contact's location, and trigger a refresh to get the latest coordinates.
Overview
Apple's FindMy app lets users share their real-time location with friends and family. The Location API exposes this data through three endpoints:
- List contacts — Get all contacts currently sharing their location
- Get contact — Get a specific contact's location by phone number or email
- Refresh — Trigger a refresh to fetch updated locations
Location data comes from Apple's FindMy service. Contacts only appear here if they have already shared their location through FindMy. This is the same person-sharing data surfaced by Apple's FindMy experience.
Prerequisites
- Location access must be provisioned for your blooio service
- Contacts must already be sharing their location through FindMy
Listing all contact locations
Retrieve cached locations for all contacts sharing their location:
curl 'https://backend.blooio.com/v2/api/location/contacts' \
-H 'Authorization: Bearer YOUR_API_KEY'const res = await fetch('https://backend.blooio.com/v2/api/location/contacts', {
headers: { 'Authorization': `Bearer ${process.env.BLOOIO_API_KEY}` }
})
const { friends } = await res.json()
console.log(friends)
// [{ handle: "+15551234567", coordinates: [37.7749, -122.4194], status: "live", last_updated: 1709... }]import os, requests
res = requests.get('https://backend.blooio.com/v2/api/location/contacts',
headers={'Authorization': f"Bearer {os.environ['BLOOIO_API_KEY']}"}
)
friends = res.json()['friends']
for friend in friends:
print(f"{friend['handle']}: {friend['coordinates']}")Getting a specific contact's location
Look up a single contact by their phone number or email:
curl 'https://backend.blooio.com/v2/api/location/contacts/%2B15551234567' \
-H 'Authorization: Bearer YOUR_API_KEY'const handle = encodeURIComponent('+15551234567')
const res = await fetch(`https://backend.blooio.com/v2/api/location/contacts/${handle}`, {
headers: { 'Authorization': `Bearer ${process.env.BLOOIO_API_KEY}` }
})
const location = await res.json()
// { handle: "+15551234567", coordinates: [37.7749, -122.4194], status: "live", last_updated: 1709... }from urllib.parse import quote
handle = quote('+15551234567', safe='')
res = requests.get(f'https://backend.blooio.com/v2/api/location/contacts/{handle}',
headers={'Authorization': f"Bearer {os.environ['BLOOIO_API_KEY']}"}
)
location = res.json()Returns 404 if the contact is not sharing their location or isn't in the cache.
Refreshing locations
Location data is cached. To get the latest coordinates, trigger a refresh:
curl -X POST 'https://backend.blooio.com/v2/api/location/contacts/refresh' \
-H 'Authorization: Bearer YOUR_API_KEY'const res = await fetch('https://backend.blooio.com/v2/api/location/contacts/refresh', {
method: 'POST',
headers: { 'Authorization': `Bearer ${process.env.BLOOIO_API_KEY}` }
})
const { friends } = await res.json()res = requests.post('https://backend.blooio.com/v2/api/location/contacts/refresh',
headers={'Authorization': f"Bearer {os.environ['BLOOIO_API_KEY']}"}
)
friends = res.json()['friends']Refreshing locations typically takes 15-20 seconds. The endpoint returns immediately with the current cache, but the latest location data may take a moment to update. For the freshest data, call refresh, wait ~20 seconds, then list contacts.
Response fields
| Field | Type | Description |
|---|---|---|
handle | string | Contact's phone number or email address |
coordinates | number[] | GPS coordinates as [latitude, longitude] |
status | string | Location freshness (see below) |
last_updated | integer | Timestamp of last location update (epoch milliseconds) |
Location status values
| Status | Meaning |
|---|---|
live | Real-time location sharing is active — coordinates are current |
shallow | Cached location from a recent session — may be minutes old |
legacy | Older cached data — location may be hours or days stale |
Common patterns
Polling for location updates
If you need periodic location tracking, call refresh on an interval and list contacts afterward:
async function trackLocations(apiKey, intervalMs = 60000) {
const headers = { 'Authorization': `Bearer ${apiKey}` }
const base = 'https://backend.blooio.com/v2/api'
setInterval(async () => {
await fetch(`${base}/location/contacts/refresh`, { method: 'POST', headers })
// Wait for the refresh to complete
await new Promise(r => setTimeout(r, 20000))
const res = await fetch(`${base}/location/contacts`, { headers })
const { friends } = await res.json()
for (const f of friends) {
console.log(`${f.handle}: [${f.coordinates}] (${f.status})`)
}
}, intervalMs)
}Avoid refreshing more frequently than once per minute. Refreshes consume resources and can take a short time to propagate. For most use cases, refreshing every 5-10 minutes is sufficient.