From 9a79b0b3e3cd073f1dfc9c930db4193b57cce0ca Mon Sep 17 00:00:00 2001 From: Yading Fang Date: Mon, 13 Jul 2026 01:42:25 +0800 Subject: [PATCH 1/2] Fix ClickToDial documentation compliance issues --- code/API_definitions/click-to-dial.yaml | 2 +- .../API_documentation/click-to-dial_API.md | 47 +++++++++++-------- 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/code/API_definitions/click-to-dial.yaml b/code/API_definitions/click-to-dial.yaml index dc388b6..90a31bd 100644 --- a/code/API_definitions/click-to-dial.yaml +++ b/code/API_definitions/click-to-dial.yaml @@ -711,7 +711,7 @@ components: data: callId: "123e4567-e89b-12d3-a456-426614174000" caller: "+12345678" - callee: "+12345678" + callee: "+87654321" status: state: "disconnected" reason: "hangUp" diff --git a/documentation/API_documentation/click-to-dial_API.md b/documentation/API_documentation/click-to-dial_API.md index 200c8fa..88499d1 100644 --- a/documentation/API_documentation/click-to-dial_API.md +++ b/documentation/API_documentation/click-to-dial_API.md @@ -12,11 +12,11 @@ The Click to Dial API provides a standardized interface to initiate and manage v ### 2.1 Prerequisites -- **Authentication**: Obtain an OpenID Connect access token from your API provider. - - ```bash - curl -X POST "{openid_token_url}" -d "grant_type=client_credentials&client_id={your_id}&client_secret={your_secret}" - ``` +- **Authentication**: Obtain an OpenID Connect access token from the API provider's Authorization Server. + - The API Consumer must use `private_key_jwt` client authentication, in accordance with the [CAMARA Security & Interoperability Profile](https://github.com/camaraproject/IdentityAndConsentManagement/blob/r4.2/documentation/CAMARA-Security-Interoperability.md#client-authentication). + - The specific authorization flows, grant types, and other parameters are determined during onboarding between the API Consumer and the API Provider. + - API requests carry the access token in the `Authorization` header as `Bearer `. + - The OpenAPI definition specifies the `openId` security scheme and the required scopes for each operation. ### 2.2 Quick Try @@ -94,13 +94,22 @@ curl -X GET "{apiRoot}/calls/{callId}/recording" \ ## 3\. Authentication and Authorization -This API uses **OpenID Connect** for authentication and authorization. Obtain your access token from your provider and use it in the Authorization header for all API requests. +This API uses **OpenID Connect** for authentication and authorization. +- The API Consumer obtains an access token from the API Provider's Authorization Server. +- The API Consumer must use `private_key_jwt` client authentication, in accordance with the [CAMARA Security & Interoperability Profile](https://github.com/camaraproject/IdentityAndConsentManagement/blob/r4.2/documentation/CAMARA-Security-Interoperability.md#client-authentication). +- The specific authorization flows, grant types, and other parameters to be used will be agreed during the onboarding process between the API Consumer and the API Provider. +- API requests carry the access token in the `Authorization` header as `Bearer `. +- The OpenAPI definition specifies the `openId` security scheme and the required scopes for each operation. ## 4\. API Documentation ### 4.1 API Version -wip +The OpenAPI definition version in the `main` branch may remain as `wip` until a release snapshot is created. Released versions and their corresponding API versions are determined by GitHub Releases, the CHANGELOG, and the OpenAPI definition under the specific release tag. + +- [OpenAPI definition](../../code/API_definitions/click-to-dial.yaml) +- [CHANGELOG](../../CHANGELOG/) +- [GitHub Releases](https://github.com/camaraproject/ClickToDial/releases) ### 4.2 Details @@ -128,12 +137,13 @@ The call session progresses through the following states (representing the `stat ##### Click to Dial Initiation Request -| Name | Description | Required | Example | -| -------------- | --------------------------------------------------- | -------- | ---------------------------- | -| caller | Calling party number (E.164, with "+") | Yes | "+12345678" | -| callee | Called party number (E.164, with "+") | Yes | "+87654321" | -| sink | (Optional) Callback URL for status notifications | No | `` | -| sinkCredential | (Optional) Callback authentication info (see below) | No | (see below) | +| Name | Description | Required | Example | +| ---------------- | --------------------------------------------------- | -------- | ------------------------------ | +| caller | Calling party number (E.164, with "+") | Yes | "+12345678" | +| callee | Called party number (E.164, with "+") | Yes | "+87654321" | +| sink | (Optional) Callback URL for status notifications | No | `` | +| sinkCredential | (Optional) Callback authentication info (see below) | No | (see below) | +| recordingEnabled | Whether call recording is enabled. | No | true | ##### sinkCredential (for `ACCESSTOKEN` type) @@ -232,9 +242,9 @@ Note: Additional common CAMARA error responses may be defined in the `CAMARA_com - Providers MUST send status notifications as CloudEvents in structured mode. The HTTP header must be `Content-Type: application/cloudevents+json`. - The CloudEvent MUST include the attributes: `id`, `source`, `type`, `specversion`, and `time`. -- The CloudEvent attribute `datacontenttype` MUST be `application/json` for the `data` payload. +- The `datacontenttype` attribute is optional in the CloudEvent schema. When present, it describes the media type of the data payload. For a JSON data payload, its value is `application/json`. -The CloudEvent `data` payload for Click-to-Dial `CallStatusChangedEvent` includes `callId`, `caller`, `callee`, `timestamp` and `status` (where `status` is an object with `state` and optional `reason`). Providers MUST set `datacontenttype` to `application/json`. +The CloudEvent `data` payload for Click-to-Dial `CallStatusChangedEvent` includes `callId`, `caller`, `callee`, `timestamp` and `status` (where `status` is an object with `state` and optional `reason`). Example CloudEvent (structured mode) — `CALL_STATUS_CHANGED_EXAMPLE` from the OpenAPI spec: @@ -250,7 +260,7 @@ Example CloudEvent (structured mode) — `CALL_STATUS_CHANGED_EXAMPLE` from the "data": { "callId": "123e4567-e89b-12d3-a456-426614174000", "caller": "+12345678", - "callee": "+12345678", + "callee": "+87654321", "status": { "state": "disconnected", "reason": "hangUp" @@ -341,10 +351,7 @@ N/A ### 4.9 Release Notes -This section lists release notes for historical versions. -The current version on the main branch is **wip**. - -- **0.1.0-alpha.1** — Initial release (archived). +Please refer to the [CHANGELOG](../../CHANGELOG/) and [GitHub Releases](https://github.com/camaraproject/ClickToDial/releases) for the history of released versions and details of changes. ## References From a323389306246eccc6e942b4b172f9a3d3f924e2 Mon Sep 17 00:00:00 2001 From: Yading Fang Date: Mon, 13 Jul 2026 19:03:48 +0800 Subject: [PATCH 2/2] Update examples and test cases to use consistent Ofcom reserved phone numbers --- code/API_definitions/click-to-dial.yaml | 8 +++---- .../click-to-dial-createCall.feature | 4 ++-- .../API_documentation/click-to-dial_API.md | 22 +++++++++---------- .../click-to-dial_User_Story.md | 7 +++--- 4 files changed, 21 insertions(+), 20 deletions(-) diff --git a/code/API_definitions/click-to-dial.yaml b/code/API_definitions/click-to-dial.yaml index 90a31bd..1ad7c87 100644 --- a/code/API_definitions/click-to-dial.yaml +++ b/code/API_definitions/click-to-dial.yaml @@ -320,9 +320,9 @@ components: - callee example: caller: - number: "+441234567890" + number: "+447700900000" callee: - number: "+441234567891" + number: "+447700900123" sink: "https://endpoint.example.com/sink" sinkCredential: credentialType: ACCESSTOKEN @@ -710,8 +710,8 @@ components: time: 2021-12-12T00:00:00Z data: callId: "123e4567-e89b-12d3-a456-426614174000" - caller: "+12345678" - callee: "+87654321" + caller: "+447700900000" + callee: "+447700900123" status: state: "disconnected" reason: "hangUp" diff --git a/code/Test_definitions/click-to-dial-createCall.feature b/code/Test_definitions/click-to-dial-createCall.feature index de85e1e..1bd8a3e 100644 --- a/code/Test_definitions/click-to-dial-createCall.feature +++ b/code/Test_definitions/click-to-dial-createCall.feature @@ -129,8 +129,8 @@ Feature: CAMARA Click to Dial API, vwip - Operation createCall @createcall_failure_same_caller_callee Scenario: Fail to initiate call when caller and callee numbers are the same - Given the request property "$.caller.number" is set to "+34666666666" - And the request property "$.callee.number" is set to "+34666666666" + Given the request property "$.caller.number" is set to "+447700900000" + And the request property "$.callee.number" is set to "+447700900000" When the request "createCall" is sent Then the response status code is 422 And the response header "Content-Type" is "application/json" diff --git a/documentation/API_documentation/click-to-dial_API.md b/documentation/API_documentation/click-to-dial_API.md index 88499d1..79acced 100644 --- a/documentation/API_documentation/click-to-dial_API.md +++ b/documentation/API_documentation/click-to-dial_API.md @@ -27,8 +27,8 @@ curl -X POST "{apiRoot}/calls" \ -H "Authorization: Bearer {access_token}" \ -H "Content-Type: application/json" \ -d '{ - "caller": { "number": "+12345678" }, - "callee": { "number": "+87654321" }, + "caller": { "number": "+447700900000" }, + "callee": { "number": "+447700900123" }, "sink": "https://yourapp.example.com/clicktodialstatusnotify", "sinkCredential": { "credentialType": "ACCESSTOKEN", @@ -45,8 +45,8 @@ curl -X POST "{apiRoot}/calls" \ ```json { "callId": "123e4567-e89b-12d3-a456-426614174000", - "caller": { "number": "+12345678" }, - "callee": { "number": "+87654321" }, + "caller": { "number": "+447700900000" }, + "callee": { "number": "+447700900123" }, "status": "initiating", "createdAt": "2025-12-11T12:00:00Z", "recordingEnabled": true @@ -87,7 +87,7 @@ curl -X GET "{apiRoot}/calls/{callId}/recording" \ ### 2.3 Key Tips -- **Number Format:** All phone numbers (caller, callee) must be in E.164 format, e.g., "+12345678". +- **Number Format:** All phone numbers (caller, callee) must be in E.164 format, e.g., "+447700900000". - **Authentication:** Use OpenID Connect; include your access token as a Bearer token. - **Status Codes:** 201 = created (POST /calls), 200 = success for reads, 204 = no content (DELETE /calls/{callId}), 400 = bad input, 401 = unauthorized, 403 = forbidden, 404 = not found, 409 = conflict, 422 = validation error. - **Debugging:** Error responses include a code and description/message. @@ -139,8 +139,8 @@ The call session progresses through the following states (representing the `stat | Name | Description | Required | Example | | ---------------- | --------------------------------------------------- | -------- | ------------------------------ | -| caller | Calling party number (E.164, with "+") | Yes | "+12345678" | -| callee | Called party number (E.164, with "+") | Yes | "+87654321" | +| caller | Calling party number (E.164, with "+") | Yes | "+447700900000" | +| callee | Called party number (E.164, with "+") | Yes | "+447700900123" | | sink | (Optional) Callback URL for status notifications | No | `` | | sinkCredential | (Optional) Callback authentication info (see below) | No | (see below) | | recordingEnabled | Whether call recording is enabled. | No | true | @@ -259,8 +259,8 @@ Example CloudEvent (structured mode) — `CALL_STATUS_CHANGED_EXAMPLE` from the "time": "2021-12-12T00:00:00Z", "data": { "callId": "123e4567-e89b-12d3-a456-426614174000", - "caller": "+12345678", - "callee": "+87654321", + "caller": "+447700900000", + "callee": "+447700900123", "status": { "state": "disconnected", "reason": "hangUp" @@ -315,8 +315,8 @@ curl -X POST "{apiRoot}/calls" \ -H "Authorization: Bearer {access_token}" \ -H "Content-Type: application/json" \ -d '{ - "caller": { "number": "+12345678" }, - "callee": { "number": "+87654321" }, + "caller": { "number": "+447700900000" }, + "callee": { "number": "+447700900123" }, "sink": "https://yourapp.example.com/clicktodialstatusnotify", "sinkCredential": { "credentialType": "ACCESSTOKEN", diff --git a/documentation/API_documentation/click-to-dial_User_Story.md b/documentation/API_documentation/click-to-dial_User_Story.md index fe3d2ab..b8d594c 100644 --- a/documentation/API_documentation/click-to-dial_User_Story.md +++ b/documentation/API_documentation/click-to-dial_User_Story.md @@ -23,8 +23,8 @@ ```json { - "caller": { "number": "+441234567890" }, - "callee": { "number": "+441234567891" }, + "caller": { "number": "+447700900000" }, + "callee": { "number": "+447700900123" }, "sink": "https://example.com/sink", "sinkCredential": { "credentialType": "ACCESSTOKEN", @@ -43,7 +43,8 @@ - CloudEvents and notifications - Providers MUST deliver status notifications as CloudEvents in structured mode (`Content-Type: application/cloudevents+json`). - - The CloudEvent MUST include `id`, `source`, `type`, `specversion`, `time`, and `datacontenttype`. `datacontenttype` for our events is `application/json`. + - The CloudEvent MUST include `id`, `source`, `type`, `specversion`, and `time`. + - The `datacontenttype` attribute is optional and, when present for the JSON payload, has the value `application/json`. - The event `data` payload for `CallStatusChangedEvent` contains `callId`, `caller`, `callee`, `timestamp` and `status` (an object): ```json