{
  "Status": true,
  "Message": "",
  "Response": {
    "post": {
      "postuid": "8dd6c738-1062-498f-b3e9-0cca6873a0c6",
      "tenantuid": "d8b744fc-2e70-4089-bb80-dd1d08f6c7b2",
      "projectuid": "239698c5-f7eb-4574-8cc8-c6568f08b3a0",
      "title": "One Time Passwords",
      "slug": "article/one-time-passwords",
      "html": "\u003Cp\u003ECustomers of DailyStory can utilize their DailyStory email and SMS marketing settings to add one time password (OTP) support for their own applications.\u003C/p\u003E\u003Ch2 id=\u0022what_is_a_one_time_password\u0022\u003EWhat is a one time password?\u003C/h2\u003E\u003Cp\u003EA One-Time Password (OTP) is a security mechanism where a user is given a password (or numeric code) that is valid for only one login session or transaction. After it\u0027s used\u2014or after a short time window\u2014it becomes invalid.\u003C/p\u003E\u003Ccite class=\u0022important\u0022\u003E\u003Cspan class=\u0022title\u0022\u003EImportant\u003C/span\u003E\u003Cp\u003EThe following content includes examples that use the DailyStory API.\u0026nbsp;\u0026nbsp;\u003Ca href=\u0022https://dev.dailystory.com/docs/create-and-use-an-api-token#/\u0022\u003EAn API key is required\u003C/a\u003E.\u0026nbsp; \u0026nbsp;\u003C/p\u003E\u003C/cite\u003E\u003Ch2 id=\u0022generating_a_one_time_password\u0022\u003EGenerating a One Time Password\u003C/h2\u003E\u003Cp\u003EMake an \u003Ccode class=\u0022inline-code\u0022\u003EHTTP POST\u003C/code\u003E request to the \u003Ca href=\u0022https://dev.dailystory.com/reference/send-one-time-password/\u0022\u003ESend One Time Password API end point\u003C/a\u003E. It must include either an email, mobile number or both. If both are present, it will default to an SMS first.\u003C/p\u003E\u003Cp\u003EFor example:\u003C/p\u003E\u003Cdiv class=\u0022code_wrapper\u0022\u003E\u003Cdiv class=\u0022code\u0022 data-language=\u0022json\u0022\u003EHTTP POST https://us-s.dailystory.com/api/v1/verification/?email=test@example.com\u0026amp;mobile=15551234567899\n\nHTTP 200 OK\n{\n    \u0026quot;Status\u0026quot;: true,\n    \u0026quot;Message\u0026quot;: \u0026quot;\u0026quot;,\n    \u0026quot;Response\u0026quot;: {\n        \u0026quot;dsid\u0026quot;: \u0026quot;3c095687f9c844d58826d5a4e994215d\u0026quot;\n    }\n}\u003C/div\u003E\u003C/div\u003E\u003Cp\u003EThe recipient will receive an SMS or email with a 6 character OTP code that is valid for 15 minutes.\u003C/p\u003E\u003Ch3 id=\u0022send_cooldown\u0022\u003ESend Cooldown\u003C/h3\u003E\u003Cp\u003EOnce an OTP is sent to a mobile number, the API enforces a \u003Cb\u003E5-minute cooldown\u003C/b\u003E before another OTP can be sent to the same number. A POST request made within the cooldown window returns HTTP 200 with an empty response and no OTP is sent.\u003C/p\u003E\u003Ccite class=\u0022recommended\u0022\u003E\u003Cspan class=\u0022title\u0022\u003ERecommended\u003C/span\u003E\u003Cp\u003EStore the\u0026nbsp;\u003Ccode class=\u0022inline-code\u0022\u003Edsid\u003C/code\u003E\u0026nbsp;returned from the send request and prompt the user to check their email or SMS before allowing a resend attempt.\u0026nbsp;\u0026nbsp;\u003C/p\u003E\u003C/cite\u003E\u003Ch3 id=\u0022rate_limiting\u0022\u003ERate Limiting\u003C/h3\u003E\u003Cp\u003ETo prevent abuse, DailyStory enforces a rate limit on OTP generation per contact. If \u003Cb\u003E10 or more OTP requests\u003C/b\u003E are made for the same contact within a \u003Cb\u003E3-hour window\u003C/b\u003E, the contact is locked out and further requests will return an error until the window expires.\u003C/p\u003E\u003Cdiv class=\u0022code_wrapper\u0022\u003E\u003Cdiv class=\u0022code\u0022 data-language=\u0022json\u0022\u003EHTTP 400\n{\n    \u0026quot;Status\u0026quot;: false,\n    \u0026quot;Message\u0026quot;: \u0026quot;The maximum number of unsuccessful OTP attempts was exceeded.\u0026quot;,\n    \u0026quot;Response\u0026quot;: {}\n}\u003C/div\u003E\u003C/div\u003E\u003Ch2 id=\u0022validating_a_one_time_password\u0022\u003EValidating a One Time Password\u003C/h2\u003E\u003Cp\u003ETo validate an OTP you will need both the OTP code and the \u003Ccode class=\u0022inline-code\u0022\u003Edsid\u003C/code\u003E associated with the OTP.\u003C/p\u003E\u003Cp\u003EMake an \u003Ccode class=\u0022inline-code\u0022\u003EHTTP GET\u003C/code\u003E request to the following API URL. In the example below the DSID is part of the URL and the otp that was received is passed in as a parameter:\u003C/p\u003E\u003Cp\u003EFor example, to verify the OTP 629316 for the dsid\u0026nbsp;3c095687f9c844d58826d5a4e994215d:\u003C/p\u003E\u003Cdiv class=\u0022code_wrapper\u0022\u003E\u003Cdiv class=\u0022code\u0022 data-language=\u0022json\u0022\u003EGET https://us-1.dailystory.com/api/v1/verification/3c095687f9c844d58826d5a4e994215d?otp=629316\n\nHTTP 200 OK\n{\n    \u0026quot;Status\u0026quot;: true,\n    \u0026quot;Message\u0026quot;: \u0026quot;The OTP is valid.\u0026quot;,\n    \u0026quot;Response\u0026quot;: {}\n}\u003C/div\u003E\u003C/div\u003E\u003Cp\u003EIf the OTP is invalid, or the validation fails:\u003C/p\u003E\u003Cdiv class=\u0022code_wrapper\u0022\u003E\u003Cdiv class=\u0022code\u0022 data-language=\u0022json\u0022\u003EHTTP 400\n{\n    \u0026quot;Status\u0026quot;: false,\n    \u0026quot;Message\u0026quot;: \u0026quot;The OTP is invalid.\u0026quot;,\n    \u0026quot;Response\u0026quot;: {}\n}\u003C/div\u003E\u003C/div\u003E\u003Ch3 id=\u0022singleuse\u0022\u003ESingle-Use\u003C/h3\u003E\u003Cp\u003EAn OTP is immediately invalidated after a successful validation and cannot be reused. Any subsequent validation attempt with the same code will return an invalid response.\u003C/p\u003E\u003Ch3 id=\u0022expiry\u0022\u003EExpiry\u003C/h3\u003E\u003Cp\u003EOTPs are valid for \u003Cb\u003E15 minutes\u003C/b\u003E from the time they are generated. An expired OTP returns the same invalid response as an incorrect code \u2014 the two cases are not distinguished in the API response.\u003C/p\u003E\u003Ch2 id=\u0022error_responses\u0022\u003EError Responses\u003C/h2\u003E\u003Cp\u003EThe following table summarizes error conditions returned by the OTP API:\u003C/p\u003E\u003Ctable border=\u00221\u0022 style=\u0022border-collapse: collapse; width: 100%;\u0022\u003E\u003Cthead\u003E\u003Ctr\u003E\u003Cth\u003ECondition\u003C/th\u003E\u003Cth\u003EHTTP Status\u003C/th\u003E\u003Cth\u003EMessage\u003C/th\u003E\u003C/tr\u003E\u003C/thead\u003E\u003Ctr\u003E\u003Ctd\u003EInvalid email format\u003C/td\u003E\u003Ctd\u003E400\u003C/td\u003E\u003Ctd\u003ECannot send OTP to contact with an invalid email address\u003C/td\u003E\u003C/tr\u003E\u003Ctr\u003E\u003Ctd\u003EInvalid mobile number format\u003C/td\u003E\u003Ctd\u003E400\u003C/td\u003E\u003Ctd\u003ECannot send OTP to contact with an invalid mobile phone number\u003C/td\u003E\u003C/tr\u003E\u003Ctr\u003E\u003Ctd\u003ERate limit exceeded\u003C/td\u003E\u003Ctd\u003E400\u003C/td\u003E\u003Ctd\u003EThe maximum number of unsuccessful OTP attempts was exceeded.\u003C/td\u003E\u003C/tr\u003E\u003Ctr\u003E\u003Ctd\u003EOTP expired\u003C/td\u003E\u003Ctd\u003E400\u003C/td\u003E\u003Ctd\u003EThe OTP is invalid.\u003C/td\u003E\u003C/tr\u003E\u003Ctr\u003E\u003Ctd\u003EOTP incorrect\u003C/td\u003E\u003Ctd\u003E400\u003C/td\u003E\u003Ctd\u003EThe OTP is invalid.\u003C/td\u003E\u003C/tr\u003E\u003Ctr\u003E\u003Ctd\u003ENo pending OTP for dsid\u003C/td\u003E\u003Ctd\u003E400\u003C/td\u003E\u003Ctd\u003EThe OTP is invalid.\u003C/td\u003E\u003C/tr\u003E\u003C/table\u003E\u003Ch2 id=\u0022frequently_asked_questions\u0022\u003EFrequently Asked Questions\u003C/h2\u003E\u003Cp\u003EBelow are some frequently asked questions about one time passwords in DailyStory.\u003C/p\u003E\u003Csection class=\u0022faq\u0022\u003E\u003Ch3\u003EWhat happens when an OTP expires?\u003C/h3\u003E\u003Carticle\u003E\u003Cp\u003EAfter 15 minutes the OTP is no longer valid. Attempting to validate an expired OTP returns the same invalid response as an incorrect code. The user must request a new OTP.\u003C/p\u003E\u003C/article\u003E\u003C/section\u003E\u003Csection class=\u0022faq\u0022\u003E\u003Ch3\u003ECan the same OTP be used more than once?\u003C/h3\u003E\u003Carticle\u003E\u003Cp\u003ENo. An OTP is deleted immediately after a successful validation. Any subsequent attempt to use the same code will return an invalid response.\u003C/p\u003E\u003C/article\u003E\u003C/section\u003E\u003Csection class=\u0022faq\u0022\u003E\u003Ch3\u003EWhat triggers the rate limit lockout?\u003C/h3\u003E\u003Carticle\u003E\u003Cp\u003E10 or more OTP generation requests for the same contact within a 3-hour window will trigger a lockout. The lockout clears automatically after the 3-hour window expires.\u003C/p\u003E\u003C/article\u003E\u003C/section\u003E\u003Csection class=\u0022faq\u0022\u003E\u003Ch3\u003EWhy didn\u0027t my customer receive a new OTP?\u003C/h3\u003E\u003Carticle\u003E\u003Cp\u003EA 5-minute cooldown is enforced between sends to the same mobile number. If a send request is made within that window, the API returns a successful response but no OTP is sent. Ask the customer to wait 5 minutes before requesting a new code.\u003C/p\u003E\u003C/article\u003E\u003C/section\u003E\u003Csection class=\u0022faq\u0022\u003E\u003Ch3\u003EWhat happens if an invalid or mismatched OTP is provided during validation?\u003C/h3\u003E\u003Carticle\u003E\u003Cp\u003EIf an incorrect OTP (e.g., 123456) is submitted and does not match the code assigned to the contact, the current OTP is immediately invalidated. Even if a subsequent attempt uses the correct code, the validation will fail because the previous mismatch triggered a security reset.\u003C/p\u003E\u003C/article\u003E\u003C/section\u003E\r\n\u003Cscript type=\u0022application/ld\u002Bjson\u0022\u003E\r\n{\r\n  \u0022@context\u0022: \u0022https://schema.org\u0022,\r\n  \u0022@type\u0022: \u0022FAQPage\u0022,\r\n  \u0022mainEntity\u0022: [\r\n{\r\n    \u0022@type\u0022: \u0022Question\u0022,\r\n    \u0022name\u0022: \u0022What happens when an OTP expires?\u0022,\r\n    \u0022acceptedAnswer\u0022: {\r\n    \u0022@type\u0022: \u0022Answer\u0022,\r\n    \u0022text\u0022: \u0022After 15 minutes the OTP is no longer valid. Attempting to validate an expired OTP returns the same invalid response as an incorrect code. The user must request a new OTP.\u0022\r\n    }\r\n},\r\n{\r\n    \u0022@type\u0022: \u0022Question\u0022,\r\n    \u0022name\u0022: \u0022Can the same OTP be used more than once?\u0022,\r\n    \u0022acceptedAnswer\u0022: {\r\n    \u0022@type\u0022: \u0022Answer\u0022,\r\n    \u0022text\u0022: \u0022No. An OTP is deleted immediately after a successful validation. Any subsequent attempt to use the same code will return an invalid response.\u0022\r\n    }\r\n},\r\n{\r\n    \u0022@type\u0022: \u0022Question\u0022,\r\n    \u0022name\u0022: \u0022What triggers the rate limit lockout?\u0022,\r\n    \u0022acceptedAnswer\u0022: {\r\n    \u0022@type\u0022: \u0022Answer\u0022,\r\n    \u0022text\u0022: \u002210 or more OTP generation requests for the same contact within a 3-hour window will trigger a lockout. The lockout clears automatically after the 3-hour window expires.\u0022\r\n    }\r\n},\r\n{\r\n    \u0022@type\u0022: \u0022Question\u0022,\r\n    \u0022name\u0022: \u0022Why didn\u0027t my customer receive a new OTP?\u0022,\r\n    \u0022acceptedAnswer\u0022: {\r\n    \u0022@type\u0022: \u0022Answer\u0022,\r\n    \u0022text\u0022: \u0022A 5-minute cooldown is enforced between sends to the same mobile number. If a send request is made within that window, the API returns a successful response but no OTP is sent. Ask the customer to wait 5 minutes before requesting a new code.\u0022\r\n    }\r\n},\r\n{\r\n    \u0022@type\u0022: \u0022Question\u0022,\r\n    \u0022name\u0022: \u0022What happens if an invalid or mismatched OTP is provided during validation?\u0022,\r\n    \u0022acceptedAnswer\u0022: {\r\n    \u0022@type\u0022: \u0022Answer\u0022,\r\n    \u0022text\u0022: \u0022If an incorrect OTP (e.g., 123456) is submitted and does not match the code assigned to the contact, the current OTP is immediately invalidated. Even if a subsequent attempt uses the correct code, the validation will fail because the previous mismatch triggered a security reset.\u0022\r\n    }\r\n}\r\n    ]\r\n}\r\n\u003C/script\u003E",
      "publish_status": 0,
      "post_type": "Article",
      "featured_image_updating": false,
      "meta_description": "Enable OTP support in your app using DailyStory email/SMS settings and API. Learn how to generate and validate One-Time Passwords for secure access.",
      "keywords": "one-time password;OTP;API;HTTP POST;validation;rate limiting;expiry;single-use;send cooldown;error responses",
      "display_toc": true,
      "has_workingcopy": false,
      "allow_indexing": true,
      "total_views": 388,
      "date_published": "2025-09-17T16:52:00",
      "date_updated": "2026-04-02T19:25:05.853",
      "date_created": "2025-09-17T16:32:07.78"
    }
  }
}