Surge

Send and verify a code

Surge's verification API sends a six-digit code to a phone number and then checks the code the user provides. It handles code generation, delivery, retry limits, and expiration — you don't manage any of that yourself.

How it works

Verification is a two-step flow:

  1. Create a verification — Surge sends a six-digit code to the number
  2. Check the code — Surge validates the code the user entered
POST /verifications → creates the verification, sends the code
POST /verifications/:id/checks → validates the user's input

Step 1 — Send the code

curl -X POST https://api.surge.app/verifications \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "phone_number": "+18015551234"
  }'
{
  "id": "vfn_01jrzhe8d9enptypyx360pcmxj",
  "phone_number": "+18015551234",
  "status": "pending",
  "attempt_count": 0
}

The user receives a text like: "Your verification code is 847291. It expires in 10 minutes."

Step 2 — Check the code

When the user submits the code in your UI, send it to Surge for verification:

curl -X POST https://api.surge.app/verifications/VERIFICATION_ID/checks \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "code": "847291"
  }'

The response includes a result field indicating whether the verification succeeded:

{
  "result": "ok",
  "verification": {
    "id": "vfn_01jrzhe8d9enptypyx360pcmxj",
    "phone_number": "+18015551234",
    "status": "verified",
    "attempt_count": 1
  }
}

Limits

  • Expiration: 10 minutes from creation. After that, the verification moves to expired status and all check attempts return expired.
  • Max attempts: 3 incorrect guesses per verification. After 3 incorrect attempts, the verification moves to exhausted status. Create a new verification and prompt the user to resend the code.

Result values

ResultMeaningWhat to do
okCode matchedGrant access
incorrectWrong codeShow an error, let the user retry
expiredCode is more than 10 minutes oldPrompt user to request a new code
already_verifiedThis verification was already approvedTreat as ok (idempotent)
exhausted3 incorrect attempts reachedCreate a new verification; do not retry the same one

Putting it together

A complete flow in Python:

from surge import Surge

surge = Surge()

# User enters their phone number
response = surge.verifications.create(phone_number="+18015551234")
verification_id = response.id

# Later: user submits the code
check = surge.verifications.check(
    id=verification_id,
    code=user_submitted_code
)

match check.result:
    case "ok" | "already_verified":
        # Grant access
        await grant_access(user)
    case "incorrect":
        return {"error": "Incorrect code. Please try again."}
    case "expired":
        return {"error": "Code expired. Request a new one."}
    case "exhausted":
        return {"error": "Too many attempts. Please request a new code."}

For deliverability quirks and edge cases, see Usage patterns.