Skip to content
View as Markdown

Inbound FaceTime calls

If you are building your own CRM or softphone, you can receive inbound FaceTime Audio calls on your lines, show a ring screen, and answer or decline from your own UI. Answering returns Agora credentials, so the same join code as outbound calls applies.

POST/answer-facetime-call-apiBearer token
On this page
FaceTime-enabled accounts only
These endpoints are available only on API accounts with FaceTime Audio enabled. Calls from accounts without the feature return 403 with error code FACETIME_NOT_ENABLED — that means the feature isn't active on your account, not that the API is down. Interested in FaceTime Audio? Contact sales@tryprojectblue.com or reach out to support to upgrade.

How it fits together

  1. A facetime.inbound.ringing webhook arrives when a call rings on one of your lines.
  2. Your UI shows a ring screen keyed on call_uuid.
  3. You answer or decline via the API.
  4. On answer you join Agora with the returned credentials.
  5. facetime.inbound.answered and facetime.inbound.ended webhooks keep your UI in sync.
  6. You hang up with /end-facetime-call-api.

1. Turn on call events for a webhook

In the Project Blue app go to Settings > API Webhooks, click Add Webhook, tick Inbound FaceTime calls, then Test & Save. Existing webhooks cannot be edited, so create a new one or a second one to the same URL. The calls box is off by default, so existing message automations are not affected.

2. Handle the ringing event

When an inbound FaceTime Audio call starts ringing on one of your lines, Project Blue POSTs facetime.inbound.ringing. Key your UI on call_uuid. A repeated ringing signal from the Mac produces one ringing webhook per call.

event"facetime.inbound.ringing"Required
Fired when an inbound FaceTime Audio call starts ringing on one of your lines.
call_uuidstringRequired
Identifies the call. Key your UI on this value and pass it to answer or decline.
direction"inbound"Required
Always inbound for this event.
fromstringRequired
The caller in E.164.
pb_line_idstring (UUID)Required
The same UUID v4 lineId returned by GET /get-lines.
linePhoneNumberstringRequired
The customer line that was called, in E.164.
ringingAtstring (ISO 8601)Required
When the call started ringing, UTC.
receivedAtstring (ISO 8601)Required
When Project Blue emitted this webhook, UTC.

Request body

call_uuidstringRequired
The call_uuid from the facetime.inbound.ringing webhook. The call must be inbound and ringing.

Response

successbooleanRequired
true when the device accepted the answer.
call_uuidstringRequired
Echo of the call you answered.
agoraobject | nullRequired
WebRTC credentials for joining the call audio. Comes from the Mac at answer time; if the Mac returns none, the service falls back to the credentials stored when the call started ringing. Can still be null on a 200. Check for null before joining.
agora can be null on a 200
A 200 means the call was answered, not that you can hear it. agora comes from the Mac at answer time; if the Mac returns none, the service falls back to the credentials it stored when the call started ringing. It can still be null on a 200. Check for it before touching the SDK.
POST/decline-facetime-call-apiBearer token

Request body

call_uuidstringRequired
The call_uuid from the facetime.inbound.ringing webhook. The call must be inbound and ringing.

If the caller already hung up between the webhook and the decline, the service treats already disconnected from the Mac as success.

3. Keep your UI in sync

facetime.inbound.answered means someone else picked up. Dismiss the ring UI if you were not the one that answered.

event"facetime.inbound.answered"Required
Fired when the call is answered by anyone: the API, the Project Blue mobile app, or the web app.
call_uuidstringRequired
Identifies the call.
fromstringRequired
The caller in E.164.
pb_line_idstring (UUID)Required
The same UUID v4 lineId returned by GET /get-lines.
linePhoneNumberstringRequired
The customer line that was called, in E.164.
answeredAtstring (ISO 8601)Required
When the call was answered, UTC.
receivedAtstring (ISO 8601)Required
When Project Blue emitted this webhook, UTC.

facetime.inbound.ended means the call is over. Tear down the ring UI and leave the Agora channel.

event"facetime.inbound.ended"Required
Fired when the call reaches a terminal state.
call_uuidstringRequired
Identifies the call.
status"ended" | "declined" | "no_answer" | "voicemail" | "busy" | "failed"Required
The terminal state.
fromstringRequired
The caller in E.164.
pb_line_idstring (UUID)Required
The same UUID v4 lineId returned by GET /get-lines.
linePhoneNumberstringRequired
The customer line that was called, in E.164.
answeredAtstring (ISO 8601) | nullRequired
When the call was answered, UTC. null when the call was never answered (declined, no_answer, voicemail, busy, failed).
endedAtstring (ISO 8601)Required
When the call reached a terminal state, UTC.
receivedAtstring (ISO 8601)Required
When Project Blue emitted this webhook, UTC.

Events

Event
When it fires
Notes
facetime.inbound.ringing
An inbound FaceTime Audio call starts ringing on one of your lines.
One ringing event per call, even if the Mac repeats the signal. Key your UI on call_uuid.
facetime.inbound.answered
The call is answered by anyone (the API, the Project Blue mobile app, or the web app).
Dismiss your ring UI if you were not the one that answered.
facetime.inbound.ended
The call reaches a terminal state.
status is one of ended, declined, no_answer, voicemail, busy, failed. answeredAt is null when the call was never answered.
No retries, so reconcile on miss
If your endpoint misses the ringing event, poll /get-facetime-call-status-api for any call_uuid you learn about later. A call is answerable only while call_status is ringing.

Status codes

200
Call answered / declined
400
Invalid or missing call_uuid
401
Missing or invalid API key
403
FACETIME_NOT_ENABLED
404
Call not found
409
Call is not an inbound call that is currently ringing
429
Rate limit exceeded
502
Device error
503
Device unreachable
500
Internal server error
API reference