openapi: 3.0.3 info: title: One Time Password SMS description: |- Service Enabling Network Function API to send short-lived OTPs (one time passwords) to a phone number via SMS and validate it afterwards, in order to verify the phone number as a proof of possession. # Relevant Definitions and concepts - **NaaS**: *Network-as-a-Service* model where Telco Network resources are exposed to third parties through APIs. In this particular API, One Time Password is exposed following this model. - **OTP**: *One Time password* is a one-time authorization code (OTAC) that is valid for only one login session or transaction. # API Functionality It enables a Service Provider (SP) to send an OTP code by SMS and validate it to verify the phone number (MSISDN) as a proof of possession. # Resources and Operations overview This API currently provides two endpoints, one to send an OTP to a given phone number and another to validate the code received as input. version: 0.5.0 servers: - url: https://apigw.omantel.om variables: host: default: https://apigw.omantel.om description: Host that serves the API basePath: default: /v1/otp description: Base path for the one time password sms API tags: - name: OTP Management description: API operations to manage OTP codes paths: /v1/otp/send-code: post: tags: - OTP Management summary: Sends a message including an OTP code to the given phone number description: |- Sends an SMS with the desired message and an OTP code to the received phone number. operationId: sendCode requestBody: content: application/json: schema: $ref: '#/components/schemas/SendCodeBody' required: true responses: '200': description: OK headers: x-correlator: description: Correlation id for the different services schema: type: string content: application/json: schema: $ref: '#/components/schemas/SendCodeResponse' '400': $ref: '#/components/responses/Generic400' '401': $ref: '#/components/responses/Generic401' '403': $ref: '#/components/responses/SendCodeForbiddenError403' '404': $ref: '#/components/responses/Generic404' '405': $ref: '#/components/responses/Generic405' '406': $ref: '#/components/responses/Generic406' '415': $ref: '#/components/responses/Generic415' '429': $ref: '#/components/responses/Generic429' '500': $ref: '#/components/responses/Generic500' '503': $ref: '#/components/responses/Generic503' '504': $ref: '#/components/responses/Generic504' security: - oAuth2ClientCredentials: [] /v1/otp/validate-code: post: tags: - OTP Management summary: Verifies the OTP received as input description: |- Verifies the code is valid for the received authenticationId operationId: validateCode requestBody: content: application/json: schema: $ref: '#/components/schemas/ValidateCodeBody' required: true responses: '204': description: The OTP was successfully validated headers: x-correlator: description: Correlation id for the different services schema: type: string '400': $ref: '#/components/responses/ValidateCodeBadRequestError400' '401': $ref: '#/components/responses/Generic401' '403': $ref: '#/components/responses/Generic403' '404': $ref: '#/components/responses/Generic404' '405': $ref: '#/components/responses/Generic405' '406': $ref: '#/components/responses/Generic406' '415': $ref: '#/components/responses/Generic415' '429': $ref: '#/components/responses/Generic429' '500': $ref: '#/components/responses/Generic500' '503': $ref: '#/components/responses/Generic503' '504': $ref: '#/components/responses/Generic504' security: - oAuth2ClientCredentials: [] components: schemas: SendCodeBody: type: object properties: phoneNumber: $ref: '#/components/schemas/PhoneNumber' message: $ref: '#/components/schemas/Message' required: - phoneNumber - message SendCodeResponse: type: object properties: authenticationId: $ref: '#/components/schemas/AuthenticationId' required: - authenticationId ValidateCodeBody: type: object properties: authenticationId: $ref: '#/components/schemas/AuthenticationId' code: $ref: '#/components/schemas/Code' required: - authenticationId - code PhoneNumber: description: A phone number belonging to the user. 'E164 with an optional +' format type: string pattern: '^\+?[0-9]{5,15}$' example: '+346661113334' Message: type: string description: Message template used to compose the content of the SMS sent to the phone number. It must include the following label indicating where to include the short code `{{code}}` pattern: .*\{\{code\}\}.* maxLength: 160 example: '{{code}} is your short code to authenticate with Cool App via SMS' AuthenticationId: type: string description: unique id of the verification attempt the code belongs to. maxLength: 36 example: ea0840f3-3663-4149-bd10-c7c6b8912105 Code: type: string description: temporal, short code to be validated maxLength: 10 example: AJY3 ErrorInfo: type: object required: - status - code - message properties: status: type: integer description: HTTP response status code code: type: string description: Code given to this error message: type: string description: Detailed error description securitySchemes: oAuth2ClientCredentials: type: oauth2 flows: clientCredentials: tokenUrl: https://apigw.omantel.om/oauth2/accesstoken scopes: one-time-password-sms:send-validate: Permission to send OTP by SMS and to validate it responses: Generic400: description: Problem with the client request headers: x-correlator: description: Correlation id for the different services schema: type: string content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: status: 400 code: INVALID_ARGUMENT message: Client specified an invalid argument, request body or query param ValidateCodeBadRequestError400: description: |- Problem with the client request. In addition to regular scenario of `INVALID_ARGUMENT`, another scenarios may exist: - Too many unsuccessful attempts (`{"code": "ONE_TIME_PASSWORD_SMS.VERIFICATION_FAILED","message": "The maximum number of attempts for this authenticationId was exceeded without providing a valid OTP"}`) - Expired authenticationId (`{"code": "ONE_TIME_PASSWORD_SMS.VERIFICATION_EXPIRED","message": "The authenticationId is no longer valid"}`) - OTP is not valid for the provided authenticationId (`{"code": "ONE_TIME_PASSWORD_SMS.INVALID_OTP","message": "The provided OTP is not valid for this authenticationId"}`) headers: x-correlator: description: Correlation id for the different services schema: type: string content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' examples: InvalidArgument: value: status: 400 code: INVALID_ARGUMENT message: Client specified an invalid argument, request body or query param VerificationFailed: value: status: 400 code: ONE_TIME_PASSWORD_SMS.VERIFICATION_FAILED message: The maximum number of attempts for this authenticationId was exceeded without providing a valid OTP VerificationExpired: value: status: 400 code: ONE_TIME_PASSWORD_SMS.VERIFICATION_EXPIRED message: The authenticationId is no longer valid InvalidOtp: value: status: 400 code: ONE_TIME_PASSWORD_SMS.INVALID_OTP message: The provided OTP is not valid for this authenticationId Generic401: description: Authentication problem with the client request headers: x-correlator: description: Correlation id for the different services schema: type: string content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: status: 401 code: UNAUTHENTICATED message: Request not authenticated due to missing, invalid, or expired credentials Generic403: description: Client does not have sufficient permission headers: x-correlator: description: Correlation id for the different services schema: type: string content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: status: 403 code: PERMISSION_DENIED message: Client does not have sufficient permissions to perform this action SendCodeForbiddenError403: description: |- Client does not have sufficient permissions to perform this action. In addition to regular scenario of `PERMISSION_DENIED`, another scenarios may exist: - Too many code requests were sent (`{"code": "ONE_TIME_PASSWORD_SMS.MAX_OTP_CODES_EXCEEDED","message": "Too many OTPs have been requested for this MSISDN. Try later."}`) - The given phoneNumber can't receive an SMS due to business reasons in the operator, e.g. fraud, receiving SMS is not supported, etc (`{"code": "ONE_TIME_PASSWORD_SMS.PHONE_NUMBER_NOT_ALLOWED","message": "Phone_number can't receive an SMS due to business reasons in the operator."}`) - The given phoneNumber is blocked to receive SMS due to any blocking business reason in the operator (`{"code": "ONE_TIME_PASSWORD_SMS.PHONE_NUMBER_BLOCKED","message": "Phone_number is blocked to receive SMS due to any blocking business reason in the operator."}`) headers: x-correlator: description: Correlation id for the different services schema: type: string content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' examples: PermissionDenied: value: status: 403 code: PERMISSION_DENIED message: Client does not have sufficient permissions to perform this action MaxOtpCodesExceeded: value: status: 403 code: ONE_TIME_PASSWORD_SMS.MAX_OTP_CODES_EXCEEDED message: Too many OTPs have been requested for this MSISDN. Try later. PhoneNumberNotAllowed: value: status: 403 code: ONE_TIME_PASSWORD_SMS.PHONE_NUMBER_NOT_ALLOWED message: Phone_number can't receive an SMS due to business reasons in the operator. Phone_number_blocked: value: status: 403 code: ONE_TIME_PASSWORD_SMS.PHONE_NUMBER_BLOCKED message: Phone_number is blocked to receive SMS due to any blocking business reason in the operator. Generic404: description: Resource Not Found headers: x-correlator: description: Correlation id for the different services schema: type: string content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: status: 404 code: NOT_FOUND message: A specified resource is not found Generic405: description: The requested method is not allowed/supported on the target resource headers: x-correlator: description: Correlation id for the different services schema: type: string content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: status: 405 code: METHOD_NOT_ALLOWED message: The requested method is not allowed/supported on the target resource Generic406: description: The server can not produce a response matching the content headers: x-correlator: description: Correlation id for the different services schema: type: string content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: status: 406 code: NOT_ACCEPTABLE message: The server can't produce a response matching the content requested by the client through Accept-* headers Generic415: description: The server refuses to accept the request because the payload format is in an unsupported format headers: x-correlator: description: Correlation id for the different services schema: type: string content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: status: 415 code: UNSUPPORTED_MEDIA_TYPE message: The server refuses to accept the request because the payload format is in an unsupported format Generic429: description: Either out of resource quota or reaching rate limiting headers: x-correlator: description: Correlation id for the different services schema: type: string content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: status: 429 code: TOO_MANY_REQUESTS message: Either out of resource quota or reaching rate limiting Generic500: description: Server error headers: x-correlator: description: Correlation id for the different services schema: type: string content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: status: 500 code: INTERNAL message: Server error Generic503: description: Service unavailable. Typically the server is down. headers: x-correlator: description: Correlation id for the different services schema: type: string content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: status: 503 code: UNAVAILABLE message: Service unavailable Generic504: description: Request time exceeded. If it happens repeatedly, consider reducing the request complexity headers: x-correlator: description: Correlation id for the different services schema: type: string content: application/json: schema: $ref: '#/components/schemas/ErrorInfo' example: status: 504 code: TIMEOUT message: Request timeout exceeded. Try later.