Introduction
The One Time Password (OTP) feature verifies a buyer's phone number to reduce fraud, enhance online payment security, and build consumer trust. If this feature is enabled, authorization requests may require the buyer to enter a one time password sent to their mobile phone. If phone verification is required, the transaction will not be authorized until the correct OTP is sent.
Key considerations
- The OTP feature is available in Germany for B2C customers only, across all Ratepay payment methods.
- Buyer must use a German mobile phone number, otherwise the transaction will be rejected.
- OTP flow triggers only based on fraud risk, not for every transaction.
- You are responsible for implementing the OTP frontend interface.
Sample Checkout Flow with OTP verification
Technical Workflow
Request authorization in the Checkout flow
First, you request an authorization as normal. If the request is accepted or rejected, the OTP flow ends. If the transaction requires OTP verification, an OTP will automatically be sent to the phone number given in the initial authorization request and the response will indicate that you have to prompt for the OTP.
UX guidelines
- Specify that only German mobile phone numbers can be used in the checkout flow
- Implement UI validation or pre-selection to ensure German phone numbers are entered. Valid formats include numbers starting with +49, 0049, or 0.
OTP verification
The buyer will receive a 6-digit OTP code on their phone and will have to enter it in your frontend. You will send this OTP to the /v1/2fa/verify endpoint. If the OTP is correct, the transaction will be authorized; otherwise the response will indicate that the OTP is incorrect and the user can try again.
If the user enters too many incorrect OTPs, the transaction will be rejected. Similarly, if the user does not enter an OTP within a certain timeframe, the transaction will be rejected. Once the transaction is rejected, you need to request a new authorization if you want to start a new OTP process.
danger
The endpoints MUST NOT be called from the frontend. This will leak your authentication token.
UX guidelines
Each OTP code is valid for 2 minutes; display a countdown timer to help buyer track the remaining validity period.
OTP resend / regeneration
Should the user not receive the OTP, another OTP can be requested by calling the regenerate endpoint. A new OTP will be sent to the same phone number; the old OTP will be invalidated. Should the user enter the first OTP after requesting a regeneration, the verification will fail. There is no feedback that the entered OTP was invalidated, it's treated as a normal wrong OTP.
OTPs cannot be regenerated immediately. API responses include a field regeneration_possible_in_seconds
that shows how long the user has to wait until a new OTP can be generated.
There is a limit on how often OTPs can be regenerated. Once you hit the limit, the last OTP stays valid but no more OTPs can be sent.
UX guidelines
- Implement a "Resend Code" button in the OTP verification flow
-
Disable the “Resend” button until the waiting period indicated in the
regeneration_possible_in_seconds
field in the API has elapsed - Each resend issues a new code. The newly issued code will have a validity period of 2 minutes.
Transaction Outcome
Regardless of whether OTP is required for a transaction or not, the transaction outcome handing is the same:
If the transaction is authorized, proceed to payment success flow.
If declined, present alternative payment methods or ask the user to restart the checkout flow.
Response results and messages
Every response from the REST API contains a result and a message field. The result field contains a value that indicates the result of the operation—either a success message or an error name. You can use result to steer your own logic.
The message field contains human readable descriptions of the result. You can show these descriptions to your user, but you must not use them to steer your logic. The descriptions might change without prior announcement.
Result code | Description |
---|---|
unexpected_client_input |
The request failed due to invalid client input, e.g. the request is invalid. |
otp_verified |
The OTP was successfully verified. |
otp_regenerated |
The OTP was successfully regenerated. |
unexpected_server_error |
The server ran into an issue that was it was not able to handle. |
otp_failed |
The OTP process failed. For example, this might happen if the verification failed too often. |
verify_attempt_failed |
The verification of an OTP failed because the code was wrong. There are still more attempts left. |
no_more_verification_attempts_left |
The verification of an OTP failed because the code was wrong. There are no more attempts left. |
transaction_not_found |
The given transaction does not exist, verification or regeneration is not possible. |
no_more_regeneration_attempts_left |
Regenerating the code is not possible, maximum number of attempts reached. |
retry_regeneration_later |
The regenerate endpoint was called too early, request has to be retried later. |
transaction_access_not_allowed |
You tried to access a transaction that you don't have access to. |
otp_live_sms_rate_limit_exceeded |
You exceeded the limit of SMS sent for the integration process. This result code can only appear in the Integration environment. |
Payment API 2.0 Example
The Authorize endpoint responds with the status OTP_REQUIRED
if an OTP process is
started:
{
"ratepay_transaction_id": "EXAMPLEID",
"result": "OTP_REQUIRED",
"payment_details": {
...
},
"created": "2025-01-01T00:00:00.000+02:00",
"authorization_expires": "2026-01-01T00:00:00.000+02:00",
"otp_details": {
"regeneration_possible_in_seconds": 60,
"time_to_live_in_seconds": 120,
"message": {
"en": "The code has been sent to your phone number 12345.",
"de": "Der Code wurde an Ihre Telefonnummer 12345 gesendet."
},
"links": {
"regenerate": {
"href": "/transaction/management/2fa/v1/regenerate/EXAMPLEID"
},
"verify": {
"href": "/transaction/management/2fa/v1/verify/EXAMPLEID"
}
}
},
"_links": {
"self": {
"href": "https://api.ratepay.com/transaction/management/v2/transactions/EXAMPLEID"
}
}
}