openapi: 3.0.3
info:
  title: Verified Caller
  description: |
    This API provides the ability to ...

    # Introduction

    Consumers of Verified Caller API can initiate the verification of the authenticity of a call from a calling party, optionally to a specific called party. A relationship between the API consumer and the service provider has to be already established for a calling party. This can be achieved by using the brand-registration API, or another mechanism agreed upon by the API consumer and the service provider.

    Verified Caller API could be useful in scenarios such as:
    - Telesales
    - Customer Support
    - Outreach efforts of NGOs.
    - Calls placed by authorities or government institutions for official matters.

    # Relevant terms and definitions

    * **callingParticipant** and **calledParticipant**: A pair of E.164 numbers representing the parties in a call.
    * **registrationId** : A unique reference to the relationship between the API consumer and the service provider.
    * **strategy**: Indicator of the requested method to be applied by the service provider to verify a call, as desired by the API consumer.
    * **timeToLive**: The period for which the verification by the service provider remains valid. A call is not considered as verified if it is placed after expiry of verification. The service provider may choose to reject a request based on the requested timeToLive value, or apply a different value than requested by the API consumer. The service provider shall observe a timeToLive value for all accepted requests. In order to reduce the risk of a spoofed call, the service provider is advised to expire the verification right away once the call is placed.
    * **dynamicDisplayName**: If strategy is 'BRAND_DISPLAY' and this parameter is provided, it overrides any pre-arranged display name presented to the callee, e.g. one set using the brand-registration API request.

    # API Functionality
    The API exposes the following endpoints/operations:
    - `/pre-announce` :
      - **POST** operation creates a new pre-announcement for a call

    # Authorization and authentication

    The "Camara Security and Interoperability Profile" provides details of how an API consumer requests an access token. Please refer to Identity and Consent Management (https://github.com/camaraproject/IdentityAndConsentManagement/) for the released version of the profile.

    The specific authorization flows to be used will be agreed upon during the onboarding process, happening between the API consumer and the API provider, taking into account the declared purpose for accessing the API, whilst also being subject to the prevailing legal framework dictated by local legislation.

    In cases where personal data is processed by the API and users can exercise their rights through mechanisms such as opt-in and/or opt-out, the use of three-legged access tokens is mandatory. This ensures that the API remains in compliance with privacy regulations, upholding the principles of transparency and user-centric privacy-by-design.

    # Identifying the device from the access token

    This API requires the API consumer to identify the called party as the subject of the API as follows:
    - When the API is invoked using a two-legged access token, the called party will be identified from the optional `calledParticipant` object, **unless** inclusion of the parameter contradicts with applicable regulations. If 'calledParticipant' parameter is not provided, the verification service is applied only based on the identity of the caller.
    - When a three-legged access token is used however, 'calledParticipant' MUST NOT be provided, as the subject will be uniquely identified from the access token.

    This approach simplifies API usage for API consumers using a three-legged access token to invoke the API by relying on the information that is associated with the access token and was identified during the authentication process.

    ## Error handling:
    - If the subject can be identified from the access token and the optional `calledParticipant` object is also included in the request, then the server will return an error with the `422 UNNECESSARY_IDENTIFIER` error code. This will be the case even if the same party is identified by these two methods, as the server is unable to make this comparison.

    # Additional CAMARA error responses

    The list of error codes in this API specification is not exhaustive. Therefore the API specification may not document some non-mandatory error statuses as indicated in `CAMARA API Design Guide`.

    Please refer to the `CAMARA_common.yaml` of the Commonalities Release associated to this API version for a complete list of error responses. The applicable Commonalities Release can be identified in the `API Readiness Checklist` document associated to this API version.

    As a specific rule, error `501 - NOT_IMPLEMENTED` can be only a possible error response if it is explicitly documented in the API.

    # Further info and support

    (FAQs will be added in a later version of the documentation)

  version: 0.1.0

        
servers:

  - url: https://api-sandbox.vf-dmp.engineering.vodafone.com/verified-caller/v0.1
    description: "Sandbox"
  - url: https://api.vf-dmp.engineering.vodafone.com/verified-caller/v0.1
    description: "Production"
    
    
  - url: https://api-test-sandbox.non-prod.vf-dmp.engineering.vodafone.com/verified-caller/v0.1
    description: "Sandbox"
tags:
  - name: Create Pre-announcement
    description: Create a call pre-announcement for a Calling and optionally a Called Party
paths:
  /pre-announce:
    post:
      tags:
        - Create Pre-announcement
      summary: Create a call pre-announcement in the service platform
      description: Create a call pre-announcement for a Calling and optionaly a Called Party that will remain valid for a specified duration.
      operationId: createPreAnnouncement
      parameters:
        - $ref: '#/components/parameters/x-correlator'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreatePreAnnouncementRequest'
            examples:
              # USING_SMS:
              #   summary: A short message is sent to the callee to verify authenticity of the caller
              #   description: A short message is sent to the callee to verify authenticity of the caller
              #   value:
              #     callingParticipant: "+123456789"
              #     calledParticipant: "+123456792"
              #     strategy: "SMS"
              #     timeToLive: 45
              #     registrationId: "d011cbff-cf79-4db3-a72b-8164aa894b37"
              USING_BRAND_DISPLAY:
                summary: A displayName is displayed to the callee to verify authenticity of the caller
                description: A displayName is displayed to the callee to verify authenticity of the caller
                value:
                  callingParticipant: "+123456791"
                  calledParticipant: "+123456792"
                  strategy: "BRAND_DISPLAY"
                  timeToLive: 45
                  registrationId: "d011cbff-cf79-4db3-a72b-8164aa894b37"
                  dynamicDisplayName: "Company X Re: Your Complaint"

      responses:
        '201':
          $ref: '#/components/responses/Create201'
        '204':
          $ref: '#/components/responses/Create204'
        '400':
          $ref: '#/components/responses/Generic400'
        '401':
          $ref: '#/components/responses/Generic401'
        '403':
          $ref: '#/components/responses/Generic403'
        '404':
          $ref: '#/components/responses/Create404'
        '409':
          $ref: '#/components/responses/Generic409'
        '422':
          $ref: '#/components/responses/Create422'
        '429':
          $ref: '#/components/responses/Generic429'
        '500':
          $ref: '#/components/responses/Generic500'
        '503':
          $ref: '#/components/responses/Generic503'

      security:
        - oAuthSample:
            - verified-caller:create
            
  /ping:
    get:
      tags:
      - Monitoring
      summary: ping operation
      description: This operation returns if the API is alive
      operationId: healthcheckPing
      # x-openapi-router-controller: app.controllers.admins_controller
      security:
        - oAuthSample:
            - verified-caller:create
      parameters:
      - $ref: '#/components/parameters/x-correlator'
      responses:
        "200":
          description: ping information returned in the result
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PongInfo'
        '400':
          $ref: '#/components/responses/Generic400'
        '401':
          $ref: '#/components/responses/Generic401'
        '403':
          $ref: '#/components/responses/Generic403'

components:
  # securitySchemes:
  #   openId:
  #     description: OpenID Connect authentication
  #     type: openIdConnect
  #     openIdConnectUrl: https://example.com/.well-known/openid-configuration
  
  securitySchemes:
    oAuthSample:
      type: oauth2
      flows:
        clientCredentials:
          tokenUrl: '/oauth2/v1/token'
          scopes:
            verified-caller:create: ""

  parameters:
    x-correlator:
      name: x-correlator
      in: header
      description: Correlation id for the different services
      schema:
        $ref: "#/components/schemas/XCorrelator"
  headers:
    x-correlator:
      description: Correlation id for the different services
      schema:
        $ref: "#/components/schemas/XCorrelator"
  schemas:
  
    PongInfo:
      description: Pong response object in return to a ping request
      type: object
      required:
        - suffix
        - client
        - startTime
        - endTime
        - responseTime
        - message
      properties:
        suffix:
          type: string
          description: Operation URI Path
          enum:
          - "/ping"
          example: "/ping"
        client:
          type: string
          description: Origin IP that request the operation
          example: "35.191.14.51"
          format: ipv4
        startTime:
          type: string
          description: Start time of the request in date-time format
          example: "2024-02-08T14:42:20.675Z"
          format: date-time
        endTime:
          type: string
          description: End time of the operation
          example: "2024-02-08T14:42:20.687Z"
          format: date-time
        responseTime:
          type: integer
          description: Time in miliseconds between startTime and endTime
          example: 12
        message:
          type: string
          description: Response message for the PING, that allways will be PONG
          example: PONG
          enum:
          - "PONG"
          
    StatusInfo:
      description: Status response object
      type: object
      required:
        - status
      properties:
        status:
          type: string
          description: The status of the API, that returns if the API is working E2E
          example: OK
          enum:
          - OK
          - KO
    XCorrelator:
      type: string
      pattern: ^[a-zA-Z0-9-_:;.\/<>{}]{0,256}$
      example: "b4333c46-49c0-4f62-80d7-f0ef930f1c46"
    PhoneNumber:
      description: A public identifier addressing a telephone subscription. In mobile networks it corresponds to the MSISDN (Mobile Station International Subscriber Directory Number). In order to be globally unique it has to be formatted in international format, according to E.164 standard, prefixed with '+'.
      type: string
      pattern: '^\+[1-9][0-9]{4,14}$'
      example: "+123456789"

    PreAnnouncementId:
      type: string
      format: uuid
      description: Unique identifier of a pre-announcement created as a result of the POST operation. Reserved for future use.
      example: "9e765f76-8037-4e5f-ba5d-e0c87c09a320"

    TimeToLive:
      type: integer
      minimum: 1
      maximum: 86400
      description: This parameter specifies for how long the pre-announcement is valid, in units of seconds. Calls processed after the call pre-announcement expiry shall be treated as not announced. If not specified, the service provider applies a default value. The service provider may enforce an upper bound of their choosing while validating the request.
      example: 60

    RegistrationId:
      type: string
      format: uuid
      description: Unique identifier of a relatonship created between the API consumer and the service platform.
      example: "9e765f76-8037-4e5f-ba5d-e0c87c09a320"

    DynamicDisplayName:
      type: string
      maxLength: 32
      description: Brand information that will be displayed to the calling party if strategy is 'BRAND_DISPLAY'. If provided, this value overrides a pre-configured display name, e.g. the displayName parameter provided in the brand-registration API request.
      example: "Company X Call Center"

    Strategy:
      type: string
      description: The method to be applied to verify the authenticity of the calling party. Absence of this parameter lets the service provider choose a default strategy which the API consumer must beware.
      enum:
        - "SMS"
        - "BRAND_DISPLAY"

    CreatePreAnnouncementRequest:
      type: object
      description: "Request object to create a call pre-announcement"
      required:
        - "callingParticipant"
        - "calledParticipant"
      properties:
        callingParticipant:
          $ref: '#/components/schemas/PhoneNumber'
        calledParticipant:
          $ref: '#/components/schemas/PhoneNumber'
        strategy:
          $ref: '#/components/schemas/Strategy'
        timeToLive:
          $ref: '#/components/schemas/TimeToLive'
        registrationId:
          $ref: '#/components/schemas/RegistrationId'
        dynamicDisplayName:
          $ref: '#/components/schemas/DynamicDisplayName'

    ExpiresAt:
      type: string
      format: date-time
      description: |
       Date when the validity of call verification will expire. The call must be placed up to this date for the service provider to verfiy it. The service provider may inlcude it especially if the API consumer did not specify a timeToLive in the request, or the service provider chose to apply a different value than requested.
       It must follow [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) and must have time zone.
       Recommended format is yyyy-MM-dd'T'HH:mm:ss.SSSZ (i.e. which allows 2023-07-03T14:27:08.312+02:00 or 2023-07-03T12:27:08.312Z)
      example: "2023-07-03T12:27:08.312Z"

    AnnouncementInfo:
      type: object
      description: "Object to represent the creation of a single pre-announcement in the service platform"
      properties:
        preAnnouncementId:
          $ref: '#/components/schemas/PreAnnouncementId'
        expiresAt:
          $ref: '#/components/schemas/ExpiresAt'

    ErrorInfo:
      description: Common schema for errors
      type: object
      required:
        - status
        - code
        - message
      properties:
        status:
          type: integer
          description: HTTP status code returned along with this error response
        code:
          type: string
          description: Code given to this error
        message:
          type: string
          description: Detailed error description

  responses:
    Create201:
      description: Successful creation of a pre-announcement
      headers:
        x-correlator:
          $ref: "#/components/headers/x-correlator"
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/AnnouncementInfo'
          examples:
            SUCCESSFUL_CREATION:
              summary: Success response with optional parameters
              description: Successful pre-announcement of a call. The service platform includes optional parameter(s) to inform the client.
              value:
                preAnnouncementId: "be5105dc-9b0e-437b-a03e-6e6ffb5e50c0"
                expiresAt: "2023-07-03T12:27:08.312Z"

    Create204:
      description: Successful creation of a pre-announcement with no content
      headers:
        x-correlator:
          $ref: "#/components/headers/x-correlator"

    Generic400:
      description: Bad Request
      headers:
        x-correlator:
          $ref: "#/components/headers/x-correlator"
      content:
        application/json:
          schema:
            allOf:
              - $ref: "#/components/schemas/ErrorInfo"
              - type: object
                properties:
                  status:
                    enum:
                      - 400
                  code:
                    enum:
                      - INVALID_ARGUMENT
          examples:
            GENERIC_400_INVALID_ARGUMENT:
              summary: Invalid argument
              description: Invalid Argument. Generic Syntax Exception
              value:
                status: 400
                code: INVALID_ARGUMENT
                message: Client specified an invalid argument, request body or query param.
    Generic401:
      description: Unauthorized
      headers:
        x-correlator:
          $ref: "#/components/headers/x-correlator"
      content:
        application/json:
          schema:
            allOf:
              - $ref: "#/components/schemas/ErrorInfo"
              - type: object
                properties:
                  status:
                    enum:
                      - 401
                  code:
                    enum:
                      - UNAUTHENTICATED
          examples:
            GENERIC_401_UNAUTHENTICATED:
              summary: Unauthenticated
              description: Request cannot be authenticated
              value:
                status: 401
                code: UNAUTHENTICATED
                message: Request not authenticated due to missing, invalid, or expired credentials.
    Generic403:
      description: Forbidden
      headers:
        x-correlator:
          $ref: "#/components/headers/x-correlator"
      content:
        application/json:
          schema:
            allOf:
              - $ref: "#/components/schemas/ErrorInfo"
              - type: object
                properties:
                  status:
                    enum:
                      - 403
                  code:
                    enum:
                      - PERMISSION_DENIED
          examples:
            GENERIC_403_PERMISSION_DENIED:
              summary: Permission denied
              description: Permission denied. OAuth2 token access does not have the required scope or when the user fails operational security
              value:
                status: 403
                code: PERMISSION_DENIED
                message: Client does not have sufficient permissions to perform this action.
    Create404:
      description: Not found
      headers:
        x-correlator:
          $ref: '#/components/headers/x-correlator'
      content:
        application/json:
          schema:
            allOf:
              - $ref: "#/components/schemas/ErrorInfo"
              - type: object
                properties:
                  status:
                    enum:
                      - 404
                  code:
                    enum:
                      - NOT_FOUND
                      - GENERIC_404_IDENTIFIER_NOT_FOUND
          examples:
            GENERIC_404_NOT_FOUND:
              summary: Generic Not Found
              description: Resource is not found
              value:
                status: 404
                code: NOT_FOUND
                message: "{{resource}} is not found"
            DEVICE_NOT_FOUND:
              summary: Device not found
              description: Device is not found
              value:
                status: 404
                code: GENERIC_404_IDENTIFIER_NOT_FOUND
                message: "Call Participant {{number}} is not known to the service provider"
    Generic409:
      description: Conflict
      headers:
        x-correlator:
          $ref: "#/components/headers/x-correlator"
      content:
        application/json:
          schema:
            allOf:
              - $ref: "#/components/schemas/ErrorInfo"
              - type: object
                properties:
                  status:
                    enum:
                      - 409
                  code:
                    enum:
                      - CONFLICT
          examples:
            GENERIC_409_CONFLICT:
              summary: Conflict
              description: Requested operation conflicts with existing data in the service platform. That may point to a mismatch between the request and existing relationship between the API consumer and the service provider.
              value:
                status: 409
                code: CONFLICT
                message: Requested operation conflicts with existing data in the service platform
    Create422:
      description: Unprocessable Content
      headers:
        x-correlator:
          $ref: '#/components/headers/x-correlator'
      content:
        application/json:
          schema:
            allOf:
              - $ref: "#/components/schemas/ErrorInfo"
              - type: object
                properties:
                  status:
                    enum:
                      - 422
                  code:
                    enum:
                      - SERVICE_NOT_APPLICABLE
                      - UNNECESSARY_IDENTIFIER
          examples:
            GENERIC_422_SERVICE_NOT_APPLICABLE:
              summary: Service not applicable
              description: Service not applicable for the provided identifier
              value:
                status: 422
                code: SERVICE_NOT_APPLICABLE
                message: The service is not available for the provided identifier.
            GENERIC_422_UNNECESSARY_IDENTIFIER:
              summary: Unnecessary identifier
              description: An explicit identifier is provided when a device or phone number has already been identified from the access token
              value:
                status: 422
                code: UNNECESSARY_IDENTIFIER
                message: The device is already identified by the access token.
    Generic429:
      description: Too Many Requests
      headers:
        x-correlator:
          $ref: "#/components/headers/x-correlator"
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorInfo"
          examples:
            GENERIC_429_QUOTA_EXCEEDED:
              description: Request is rejected due to exceeding a business quota limit
              value:
                status: 429
                code: QUOTA_EXCEEDED
                message: Either out of resource quota or reaching rate limiting.
            GENERIC_429_TOO_MANY_REQUESTS:
              description: API Server request limit is overpassed
              value:
                status: 429
                code: TOO_MANY_REQUESTS
                message: Either out of resource quota or reaching rate limiting.
    Generic500:
      description: Internal server error
      headers:
        x-correlator:
          $ref: "#/components/headers/x-correlator"
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorInfo"
          examples:
            GENERIC_500_INTERNAL:
              summary: Generic Internal
              description: Problem in Server side. Regular Server Exception
              value:
                status: 500
                code: INTERNAL
                message: "Internal server error"
    Generic503:
      description: Service unavailable
      headers:
        x-correlator:
          $ref: "#/components/headers/x-correlator"
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorInfo"
          examples:
            GENERIC_503_UNAVAILABLE:
              summary: Generic Unavailable
              description: Service is not available. Temporary situation usually related to maintenance process in the server side
              value:
                status: 503
                code: UNAVAILABLE
                message: "Service unavailable"