# CrazyPIN API integration - send and check SMS OTP codes, API key and idempotency

> Category: Premium Features
> Canonical URL: https://crazytel.com.au/knowledgebase/article/crazypin-api-integration

CrazyPIN API: get your API key, send an SMS OTP with POST /verifications, check the code, resend and cancel, and retry safely with Idempotency-Key. Server-side JSON API at api.crazytel.io.

#1 CrazyPIN API integration - send and check SMS OTP codes, API key and idempotency




Connect your website or app to CrazyPIN, the Crazytel SMS one-time passcode (OTP) verification API. Get your API key in MyAccount, send a six-digit code to an Australian mobile, check the code the customer enters, and retry safely with idempotency keys. All calls are made from your server.




Set up a profile first: see CrazyPIN SMS one-time passcodes - setup. Full technical reference: https://crazytel.io/docs#/CrazyPIN%20SMS%20Verification.





#2 1. Get your API key




Go to Premium Features &gt; CrazyPIN &gt; API Management. Click Show to reveal your key, or Copy to copy it.



- Keep the key on your server only. Never put it in a web page, mobile app, screenshot or support ticket.

- Regenerate key creates a new key and the old one stops working immediately. Update your servers first or straight after.

- The key is shared by every Crazytel API product on your account, including SMS.





#2 2. Make API calls from your server




SettingValue


Base URLhttps://api.crazytel.io/api/v1/verify
Authentication headerx-crazytel-api-key: your_api_key
FormatJSON (Content-Type: application/json)
Full documentationhttps://crazytel.io/docs#/CrazyPIN%20SMS%20Verification




MethodPathPurpose


GET/sendersList caller IDs you can send from
POST/profilesCreate a profile (starts disabled)
GET/profiles and /profiles/{profile_id}List or read profiles
PATCH/profiles/{profile_id}Change settings, enable or disable
POST/verificationsSend a code
GET/verifications/{id}Read status
POST/verifications/{id}/checksCheck a code
POST/verifications/{id}/resendSend a fresh code
POST/verifications/{id}/cancelCancel a pending verification





#2 3. The normal flow




#3 Step A. Send a code




Send a code when the customer asks for one:




curl -X POST "https://api.crazytel.io/api/v1/verify/verifications" \
  -H "x-crazytel-api-key: your_api_key" \
  -H "Idempotency-Key: 6f1c2b7e-unique-per-send" \
  -H "Content-Type: application/json" \
  -d '{
    "profile_id": "YOUR_PROFILE_ID",
    "to": "0491570006",
    "channel": "sms",
    "purpose": "signup",
    "reference": "signup-flow-001"
  }'

- to can be 04xxxxxxxx, 614xxxxxxxx or +614xxxxxxxx.

- purpose is one of signup, login, password_reset, phone_change, transaction.

- reference is an ID your own backend creates for this flow. Do not put personal details or secrets in it.

- The response includes an id. Store it with your flow, because you need it to check the code.





#3 Step B. Check the code


Check the code when the customer enters it:




curl -X POST "https://api.crazytel.io/api/v1/verify/verifications/VERIFICATION_ID/checks" \
  -H "x-crazytel-api-key: your_api_key" \
  -H "Idempotency-Key: 9d84a0c1-unique-per-check" \
  -H "Content-Type: application/json" \
  -d '{"code": "012345"}'

- Send the code as text so leading zeros stay.

- valid: true and status: "approved" means the code was correct.

- valid: false with fewer check_attempts_remaining means a wrong code. After the last wrong guess you will get verification_attempts_exhausted.





#3 Step C. Finish the original action once


Only the first successful check may complete your signup, login or other action. Make that step atomic on your side. Status lookups, delivery receipts and repeated successful checks are not new approvals.





#2 4. Idempotency keys (safe retries)




Send a unique Idempotency-Key header (8 to 255 printable characters, no spaces) with every send, resend and check. If a request times out, repeat the same request with the same key and body. You will get the saved result and nothing happens twice. Keep keys for at least 24 hours. Never use a new key just because you did not get a response: the SMS may already have been sent.





#2 5. Show a countdown correctly




Use expires_at from the response for your countdown, not the time you sent the SMS. Messages can arrive late. Resending does not restart the timer.





#2 Related



- CrazyPIN SMS one-time passcodes - setup

- CrazyPIN limits, security and troubleshooting
