
Connecting an Apple Account to Figment is one step. Getting each service into a ready state is not. iMessage, Contacts, Calendar, and Reminders each have their own Apple-side approval, sync, and Mac permission sequence. Check each service's state before your app makes requests against it—a signed-in account does not automatically mean a ready service. For the developer overview, see OAuth for iCloud.
Figment tracks a state for every service on a connection. The state appears in the connection.services map returned by GET /v1/connections/{connection_id}.
| State | Meaning |
|---|---|
connecting | Initial setup in progress |
needs_approval | A user action is required before this service can proceed |
syncing | The service is active but local data is still downloading |
ready | The service is available for requests within your granted scopes |
offline | The Mac worker has lost contact; most cases recover automatically |
reconnect_required | The user must re-authorize part of the connection |
revoked | The user removed access; will not recover without a new grant |
Non-ready services reject operations. A service in syncing is not yet ready—reads will fail. Check state at the start of each session, not only at connection time.
Register your app first to get a client_id and to set your exact HTTPS redirect URI. The sandbox is free; a live connection is $29/month per active Apple connection, and access starts after setup.
OAuth flow:
Build an authorization URL to https://figment.so/apple-connect/authorize. Include client_id, your exact redirect_uri, response_type=code, the scopes you need, a state value, and a fresh PKCE code_challenge with code_challenge_method=S256.
Redirect the user to that URL. Figment's hosted screen signs the user into Figment and presents the app-consent step, where the user selects an Apple Account connection and approves the requested scopes. Apple sign-in and trusted-device approval on the Mac are part of connection setup and happen before the OAuth grant is issued. All codes and tokens are issued by Figment, not Apple.
Figment redirects to your redirect_uri with code and state. Verify state matches before continuing.
Exchange the code at POST https://figment.so/api/apple-connect/oauth/token with grant_type=authorization_code, client_id, redirect_uri, code, and code_verifier as application/x-www-form-urlencoded.
The response includes access_token, refresh_token, expires_in, scope, and connection_id. Store the connection_id—it identifies this Apple connection in every subsequent API call. Access tokens expire after 900 seconds; refresh using grant_type=refresh_token with client_id and refresh_token, and store the rotated refresh token. Your app never receives the Apple password.
The table covers the services with a public customer endpoint. After completing the OAuth flow, confirm each service your app depends on reaches ready before making data requests.
| Service | Availability | Apple-side requirement | First-time note |
|---|---|---|---|
| iMessage | Live — requires account setup and approval; live access depends on capacity | Trusted-device approval; Messages in iCloud enabled on iPhone and Mac | History can be incomplete even when ready; check historyComplete on list responses (Apple guide) |
| SMS / MMS / RCS | Live — same connection as iMessage | iPhone must be on, online, and signed into the same Apple Account | Messages in iCloud includes SMS, MMS, and RCS automatically; a separate forwarding switch is not required when Messages in iCloud is enabled (Apple guide) |
| Contacts | Synthetic sandbox only — live access unavailable | — | Sandbox returns invented data; every response includes "scope": "synthetic sandbox data" |
| Calendar | Synthetic sandbox only — live access unavailable | Supply both start and end ISO timestamps; range must not exceed 366 days | Sandbox calendar items are synthetic; end must follow start |
| Reminders | Synthetic sandbox only — live access unavailable | — | completed defaults to false; pass completed=true to include completed items |
Other Apple services—Mail, Photos, iCloud Drive, Notes, Keychain, Safari, Voice Memos, Find My, Home, Shortcuts, and Books—sync locally on the connected Mac but have no public Figment customer endpoint. Figment does not currently expose a customer API for them.
After the OAuth exchange you have a connection_id. Fetch the connection to read per-service state:
GET https://figment.so/api/apple-connect/v1/connections/con_...
Authorization: Bearer ACCESS_TOKEN
Each entry in connection.services is an object with state, reason, and observedAt (epoch milliseconds). Only services on the granted connection appear:
{
"connection": {
"id": "con_...",
"mode": "sandbox",
"services": {
"messages": {
"state": "ready",
"reason": null,
"observedAt": 1731369600000
},
"contacts": {
"state": "syncing",
"reason": null,
"observedAt": 1731369590000
}
}
}
}
Only proceed with service-specific operations once that service shows ready. For iMessage, also check historyComplete on list responses—native history can still be downloading after the service reaches ready. A ready state does not guarantee delivery of outbound messages.
offline usually means the Mac has temporarily lost contact. Most cases resolve automatically; if the state persists, confirm the Mac is on and connected to the network.
reconnect_required means the user must re-authorize part of the connection—typically because a trusted-device session expired or a system permission was revoked. Send the user back through the authorization flow to restore it. For Mac system permissions (Full Disk Access, Automation, Contacts, Calendars), see Grant the Mac Permissions Your Connector Needs. For iMessage history that is incomplete after recovery, see Fix Missing iMessage History on a Connected Mac.
Register your app and start in the free sandbox. Each active live Apple connection is $29/month—access starts after setup. Manage grants and revocations at your account page. For safe sending and idempotency, see Prevent Duplicate iMessages After a Timeout.