{"openapi":"3.1.0","info":{"title":"wtsp.dev","version":"1.0.0","summary":"WhatsApp data for AI agents, paid per request.","description":"Send a phone number, learn whether it is on WhatsApp, or get its WhatsApp profile, business details, profile photo or carrier. Every request is paid on its own: USDC on Base with x402, or stablecoins on Tempo with MPP. No sign-up. Prepaid API keys are optional.","x-guidance":"Every endpoint is a GET with ?phone=<number with its country code>. Pay with any x402 client (npx wtsp, @x402/fetch, AgentCash), any MPP client (npx mppx), or send a prepaid key as Authorization: Bearer wtsp_…. Only answers are charged; malformed numbers and failed lookups are free. Full guide: https://wtsp.dev/llms.txt","contact":{"url":"https://wtsp.dev"}},"servers":[{"url":"https://wtsp.dev"}],"x-agentcash-guidance":{"llmsTxtUrl":"https://wtsp.dev/llms.txt"},"tags":[{"name":"WhatsApp","description":"Lookups answered by WhatsApp itself."},{"name":"Phone","description":"Numbering-plan facts, no WhatsApp lookup involved."},{"name":"Credits","description":"Prepaid credit for API-key access."}],"paths":{"/v1/exists":{"get":{"operationId":"exists","summary":"WhatsApp check","description":"Whether a number has a WhatsApp account, and nothing else: the cheapest way to clean a list before paying for profiles. /v1/profile gives the same answer plus the account's details. Query param: phone, with country code (e.g. +14155552671). Every answer is charged, “not on WhatsApp” included; a lookup WhatsApp does not answer is free.","tags":["WhatsApp"],"security":[{},{"apiKey":[]}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.004"},"protocols":[{"x402":{}},{"mpp":{"method":"tempo","intent":"charge","currency":"USD"}}]},"parameters":[{"name":"phone","in":"query","required":true,"description":"Phone number with its country code, e.g. +14155552671. The + is optional; spaces, dashes and a leading 00 are fine.","schema":{"type":"string","example":"+14155552671"}}],"responses":{"200":{"description":"The answer, “not on WhatsApp” included. With an API key, the wtsp-credits-remaining header gives the credit left.","content":{"application/json":{"schema":{"type":"object","properties":{"phone":{"type":"string","description":"The number looked up, in E.164."},"hasWhatsApp":{"type":"boolean","description":"Whether the number is a registered WhatsApp account. `false` is a definitive answer, not a failure."},"checkedAt":{"type":"string","description":"When this answer was fetched from WhatsApp (ISO 8601)."}},"required":["phone","hasWhatsApp","checkedAt"]},"example":{"phone":"+14155552671","hasWhatsApp":true,"checkedAt":"2026-10-09T18:24:03.000Z"}}}},"400":{"description":"Malformed number, rejected before any payment is asked for. Not charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Payment required, or the payment sent was invalid. x402 v2 requirements are in the PAYMENT-REQUIRED header, the MPP challenge in WWW-Authenticate; with an API key, the credit ran out. Not charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"WhatsApp did not answer. The payment is cancelled, never settled. Not charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/profile":{"get":{"operationId":"profile","summary":"WhatsApp profile","description":"Whether a number is on WhatsApp and, if so: personal or business account, about text, country, linked devices and whether it runs on the Cloud API. Businesses add their public profile: name, description, categories, email, websites, address, coordinates, hours, join date and Facebook page. No photo; /v1/profile/full adds it. Query param: phone, with country code (e.g. +14155552671). Every answer is charged, “not on WhatsApp” included; a lookup WhatsApp does not answer is free.","tags":["WhatsApp"],"security":[{},{"apiKey":[]}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.006"},"protocols":[{"x402":{}},{"mpp":{"method":"tempo","intent":"charge","currency":"USD"}}]},"parameters":[{"name":"phone","in":"query","required":true,"description":"Phone number with its country code, e.g. +14155552671. The + is optional; spaces, dashes and a leading 00 are fine.","schema":{"type":"string","example":"+14155552671"}}],"responses":{"200":{"description":"The answer, “not on WhatsApp” included. With an API key, the wtsp-credits-remaining header gives the credit left.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"phone":{"type":"string","description":"The number looked up, in E.164."},"hasWhatsApp":{"type":"boolean","const":true,"description":"The number is a registered WhatsApp account."},"accountType":{"type":"string","enum":["business","personal"],"description":"`business` when WhatsApp published a business profile."},"identity":{"type":"object","properties":{"countryCode":{"description":"Country WhatsApp reports for the account (ISO 3166-1 alpha-2), not one guessed from the prefix.","type":["string","null"]},"lid":{"description":"WhatsApp's internal account id. Numbers that share one account share it.","type":["string","null"]}},"required":["countryCode","lid"]},"profile":{"type":"object","properties":{"about":{"description":"The \"about\" (status) text.","type":["string","null"]},"aboutRestricted":{"type":"boolean","description":"True when an about text exists but privacy settings hide it, so `about` is empty."}},"required":["about","aboutRestricted"]},"devices":{"description":"Absent on the rare occasion WhatsApp sends no device list.","type":"object","properties":{"count":{"type":"number","description":"Linked devices including the phone itself, so 1 means phone only."},"hosted":{"type":"boolean","description":"Served by the WhatsApp Business Platform (Cloud API) rather than a phone: a strong real-business signal."}},"required":["count","hosted"]},"business":{"anyOf":[{"type":"object","properties":{"displayName":{"description":"Public business name. Personal accounts publish no name at all.","type":["string","null"]},"description":{"type":["string","null"]},"categories":{"type":"array","items":{"type":"string"},"description":"Every category the business picked; often more than one."},"email":{"type":["string","null"]},"websites":{"type":"array","items":{"type":"string"}},"address":{"type":["string","null"]},"latitude":{"type":["number","null"]},"longitude":{"type":["number","null"]},"timezone":{"description":"IANA zone the opening hours are in.","type":["string","null"]},"hours":{"type":"array","items":{"type":"object","properties":{"day":{"type":"string","description":"Day of week, e.g. `mon`."},"mode":{"type":"string","description":"`specific_hours`, `open_24h` or `appointment_only` (times are null then)."},"openTime":{"description":"Opening time, HH:MM.","type":["string","null"]},"closeTime":{"description":"Closing time, HH:MM.","type":["string","null"]}},"required":["day","mode","openTime","closeTime"]},"description":"Opening hours per day."},"memberSince":{"description":"When the business joined, as WhatsApp words it: \"Joined in January, 2026\".","type":["string","null"]},"memberSinceTs":{"description":"The same moment as a unix timestamp (seconds).","type":["number","null"]},"businessType":{"description":"`smb` for a small business, or an enterprise tier.","type":["string","null"]},"verifiedLevel":{"description":"Meta verification tier.","type":["string","null"]},"cartEnabled":{"type":"boolean","description":"Whether the account sells through a WhatsApp cart."},"commerceExperience":{"type":["string","null"]},"automatedType":{"description":"Set when WhatsApp flags the account as automated (a bot).","type":["string","null"]},"linkedFacebookPage":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"name":{"type":["string","null"]},"likes":{"type":["number","null"]}},"required":["id","name","likes"]},{"type":"null"}],"description":"Linked Facebook page and its follower count."}},"required":["displayName","description","categories","email","websites","address","latitude","longitude","timezone","hours","memberSince","memberSinceTs","businessType","verifiedLevel","cartEnabled","commerceExperience","automatedType","linkedFacebookPage"]},{"type":"null"}],"description":"Business profile; null for personal accounts."},"checkedAt":{"type":"string","description":"When this answer was fetched from WhatsApp (ISO 8601)."}},"required":["phone","hasWhatsApp","accountType","identity","profile","business","checkedAt"]},{"type":"object","properties":{"phone":{"type":"string","description":"The number looked up, in E.164."},"hasWhatsApp":{"type":"boolean","const":false,"description":"The number is not on WhatsApp: a definitive answer, not a failure."},"checkedAt":{"type":"string","description":"When this answer was fetched from WhatsApp (ISO 8601)."}},"required":["phone","hasWhatsApp","checkedAt"]}]},"example":{"phone":"+14155552671","hasWhatsApp":true,"accountType":"business","identity":{"countryCode":"US","lid":"258166877098174@lid"},"profile":{"about":"Fresh groceries, delivered daily 🍋","aboutRestricted":false},"devices":{"count":2,"hosted":false},"business":{"displayName":"Fresh Market SF","description":"Neighbourhood grocery with same-day delivery across San Francisco.","categories":["Grocery Store","Food delivery"],"email":"hello@freshmarket.example","websites":["https://freshmarket.example"],"address":"123 Market St, San Francisco, CA 94103","latitude":37.7749,"longitude":-122.4194,"timezone":"America/Los_Angeles","hours":[{"day":"mon","mode":"specific_hours","openTime":"08:00","closeTime":"20:00"},{"day":"sat","mode":"specific_hours","openTime":"09:00","closeTime":"18:00"},{"day":"sun","mode":"appointment_only","openTime":null,"closeTime":null}],"memberSince":"Joined in March, 2021","memberSinceTs":1615420800,"businessType":"smb","verifiedLevel":"unknown","cartEnabled":true,"commerceExperience":"none","automatedType":"unknown","linkedFacebookPage":{"id":"100064523310987","name":"Fresh Market SF","likes":1840}},"checkedAt":"2026-10-09T18:24:03.000Z"}}}},"400":{"description":"Malformed number, rejected before any payment is asked for. Not charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Payment required, or the payment sent was invalid. x402 v2 requirements are in the PAYMENT-REQUIRED header, the MPP challenge in WWW-Authenticate; with an API key, the credit ran out. Not charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"WhatsApp did not answer. The payment is cancelled, never settled. Not charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/profile/full":{"get":{"operationId":"profileFull","summary":"WhatsApp profile + photo","description":"Everything /v1/profile returns, plus the profile photo as a permanent URL and a content hash: an unchanged hash means an unchanged photo. The URL is null when the account has no photo or hides it. Query param: phone, with country code (e.g. +14155552671). Every answer is charged, “not on WhatsApp” included; a lookup WhatsApp does not answer is free.","tags":["WhatsApp"],"security":[{},{"apiKey":[]}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.01"},"protocols":[{"x402":{}},{"mpp":{"method":"tempo","intent":"charge","currency":"USD"}}]},"parameters":[{"name":"phone","in":"query","required":true,"description":"Phone number with its country code, e.g. +14155552671. The + is optional; spaces, dashes and a leading 00 are fine.","schema":{"type":"string","example":"+14155552671"}}],"responses":{"200":{"description":"The answer, “not on WhatsApp” included. With an API key, the wtsp-credits-remaining header gives the credit left.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"phone":{"type":"string","description":"The number looked up, in E.164."},"hasWhatsApp":{"type":"boolean","const":true,"description":"The number is a registered WhatsApp account."},"accountType":{"type":"string","enum":["business","personal"],"description":"`business` when WhatsApp published a business profile."},"identity":{"type":"object","properties":{"countryCode":{"description":"Country WhatsApp reports for the account (ISO 3166-1 alpha-2), not one guessed from the prefix.","type":["string","null"]},"lid":{"description":"WhatsApp's internal account id. Numbers that share one account share it.","type":["string","null"]}},"required":["countryCode","lid"]},"profile":{"type":"object","properties":{"about":{"description":"The \"about\" (status) text.","type":["string","null"]},"aboutRestricted":{"type":"boolean","description":"True when an about text exists but privacy settings hide it, so `about` is empty."},"picUrl":{"description":"Permanent URL of the profile photo; null when there is none or privacy settings hide it.","type":["string","null"]},"picHash":{"description":"Content hash of the photo. Unchanged hash, unchanged photo.","type":["string","null"]}},"required":["about","aboutRestricted","picUrl","picHash"]},"devices":{"description":"Absent on the rare occasion WhatsApp sends no device list.","type":"object","properties":{"count":{"type":"number","description":"Linked devices including the phone itself, so 1 means phone only."},"hosted":{"type":"boolean","description":"Served by the WhatsApp Business Platform (Cloud API) rather than a phone: a strong real-business signal."}},"required":["count","hosted"]},"business":{"anyOf":[{"type":"object","properties":{"displayName":{"description":"Public business name. Personal accounts publish no name at all.","type":["string","null"]},"description":{"type":["string","null"]},"categories":{"type":"array","items":{"type":"string"},"description":"Every category the business picked; often more than one."},"email":{"type":["string","null"]},"websites":{"type":"array","items":{"type":"string"}},"address":{"type":["string","null"]},"latitude":{"type":["number","null"]},"longitude":{"type":["number","null"]},"timezone":{"description":"IANA zone the opening hours are in.","type":["string","null"]},"hours":{"type":"array","items":{"type":"object","properties":{"day":{"type":"string","description":"Day of week, e.g. `mon`."},"mode":{"type":"string","description":"`specific_hours`, `open_24h` or `appointment_only` (times are null then)."},"openTime":{"description":"Opening time, HH:MM.","type":["string","null"]},"closeTime":{"description":"Closing time, HH:MM.","type":["string","null"]}},"required":["day","mode","openTime","closeTime"]},"description":"Opening hours per day."},"memberSince":{"description":"When the business joined, as WhatsApp words it: \"Joined in January, 2026\".","type":["string","null"]},"memberSinceTs":{"description":"The same moment as a unix timestamp (seconds).","type":["number","null"]},"businessType":{"description":"`smb` for a small business, or an enterprise tier.","type":["string","null"]},"verifiedLevel":{"description":"Meta verification tier.","type":["string","null"]},"cartEnabled":{"type":"boolean","description":"Whether the account sells through a WhatsApp cart."},"commerceExperience":{"type":["string","null"]},"automatedType":{"description":"Set when WhatsApp flags the account as automated (a bot).","type":["string","null"]},"linkedFacebookPage":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"name":{"type":["string","null"]},"likes":{"type":["number","null"]}},"required":["id","name","likes"]},{"type":"null"}],"description":"Linked Facebook page and its follower count."}},"required":["displayName","description","categories","email","websites","address","latitude","longitude","timezone","hours","memberSince","memberSinceTs","businessType","verifiedLevel","cartEnabled","commerceExperience","automatedType","linkedFacebookPage"]},{"type":"null"}],"description":"Business profile; null for personal accounts."},"checkedAt":{"type":"string","description":"When this answer was fetched from WhatsApp (ISO 8601)."}},"required":["phone","hasWhatsApp","accountType","identity","profile","business","checkedAt"]},{"type":"object","properties":{"phone":{"type":"string","description":"The number looked up, in E.164."},"hasWhatsApp":{"type":"boolean","const":false,"description":"The number is not on WhatsApp: a definitive answer, not a failure."},"checkedAt":{"type":"string","description":"When this answer was fetched from WhatsApp (ISO 8601)."}},"required":["phone","hasWhatsApp","checkedAt"]}]},"example":{"phone":"+14155552671","hasWhatsApp":true,"accountType":"business","identity":{"countryCode":"US","lid":"258166877098174@lid"},"profile":{"about":"Fresh groceries, delivered daily 🍋","aboutRestricted":false,"picUrl":"https://wtsp.dev/photos/258166877098174/tkphavoFaBWOiNjZo_B5L-uG8Bw4BjhRDNPgDs-1vp4.jpg","picHash":"tkphavoFaBWOiNjZo/B5L+uG8Bw4BjhRDNPgDs+1vp4="},"devices":{"count":2,"hosted":false},"business":{"displayName":"Fresh Market SF","description":"Neighbourhood grocery with same-day delivery across San Francisco.","categories":["Grocery Store","Food delivery"],"email":"hello@freshmarket.example","websites":["https://freshmarket.example"],"address":"123 Market St, San Francisco, CA 94103","latitude":37.7749,"longitude":-122.4194,"timezone":"America/Los_Angeles","hours":[{"day":"mon","mode":"specific_hours","openTime":"08:00","closeTime":"20:00"},{"day":"sat","mode":"specific_hours","openTime":"09:00","closeTime":"18:00"},{"day":"sun","mode":"appointment_only","openTime":null,"closeTime":null}],"memberSince":"Joined in March, 2021","memberSinceTs":1615420800,"businessType":"smb","verifiedLevel":"unknown","cartEnabled":true,"commerceExperience":"none","automatedType":"unknown","linkedFacebookPage":{"id":"100064523310987","name":"Fresh Market SF","likes":1840}},"checkedAt":"2026-10-09T18:24:03.000Z"}}}},"400":{"description":"Malformed number, rejected before any payment is asked for. Not charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Payment required, or the payment sent was invalid. x402 v2 requirements are in the PAYMENT-REQUIRED header, the MPP challenge in WWW-Authenticate; with an API key, the credit ran out. Not charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"WhatsApp did not answer. The payment is cancelled, never settled. Not charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/carrier":{"get":{"operationId":"carrier","summary":"Carrier lookup","description":"The carrier and line type of any number, from the numbering plan: the network its range was issued to, mobile, fixed line or VoIP, plus country, region, time zones and national and international formats. Works whether or not the number is on WhatsApp. Ported numbers report their original carrier. Query param: phone, with country code (e.g. +447400123456). Only charged when a carrier is on record; numbers without one (the US and Canada among them) get a free 404.","tags":["Phone"],"security":[{},{"apiKey":[]}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.004"},"protocols":[{"x402":{}},{"mpp":{"method":"tempo","intent":"charge","currency":"USD"}}]},"parameters":[{"name":"phone","in":"query","required":true,"description":"Phone number with its country code, e.g. +14155552671. The + is optional; spaces, dashes and a leading 00 are fine.","schema":{"type":"string","example":"+447400123456"}}],"responses":{"200":{"description":"The answer, “not on WhatsApp” included. With an API key, the wtsp-credits-remaining header gives the credit left.","content":{"application/json":{"schema":{"type":"object","properties":{"phone":{"type":"string","description":"The number looked up, in E.164."},"carrier":{"type":"string","description":"Network the number range was issued to. Ported numbers keep their original carrier."},"lineType":{"type":"string","description":"`mobile`, `fixed line`, `fixed line or mobile`, `voip`, `toll free`…"},"isMobile":{"description":"Null where a country hands mobiles and landlines out of one shared range.","type":["boolean","null"]},"country":{"type":"string","description":"ISO 3166-1 alpha-2 country of the number."},"countryName":{"type":"string"},"flag":{"type":"string"},"countryCallingCode":{"type":"string"},"location":{"description":"Town or region the number was issued in, where published.","type":["string","null"]},"timezones":{"type":"array","items":{"type":"string"}},"international":{"type":"string","description":"The number in international format."},"national":{"type":"string","description":"The number as dialled inside its country."}},"required":["phone","carrier","lineType","isMobile","country","countryName","flag","countryCallingCode","location","timezones","international","national"]},"example":{"phone":"+447400123456","carrier":"Three","lineType":"mobile","isMobile":true,"country":"GB","countryName":"United Kingdom","flag":"🇬🇧","countryCallingCode":"+44","location":null,"timezones":["Europe/London"],"international":"+44 7400 123456","national":"07400 123456"}}}},"400":{"description":"Malformed number, rejected before any payment is asked for. Not charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Payment required, or the payment sent was invalid. x402 v2 requirements are in the PAYMENT-REQUIRED header, the MPP challenge in WWW-Authenticate; with an API key, the credit ran out. Not charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Carrier lookup only: no carrier on record for the number. Not charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/credits":{"post":{"operationId":"buyCredits","summary":"Buy API credit","description":"Buy prepaid credit in whole USDC, paid with x402. Without an Authorization header a new API key is issued and returned once; with one, that key is topped up. The payment settles before any credit is written.","tags":["Credits"],"security":[{},{"apiKey":[]}],"x-payment-info":{"price":{"mode":"dynamic","currency":"USD","min":"1","max":"500"},"protocols":[{"x402":{}}]},"parameters":[{"name":"amount","in":"query","required":true,"description":"Whole USDC to add, from 1 to 500. It is also the price.","schema":{"type":"integer","minimum":1,"maximum":500,"example":10}}],"responses":{"200":{"description":"Credit added.","content":{"application/json":{"schema":{"type":"object","properties":{"key":{"description":"The new API key, shown this once. Null when an existing key was topped up.","type":["string","null"]},"keyPrefix":{"type":"string","description":"The key's first characters, to tell keys apart."},"added":{"type":"string","description":"USDC added by this purchase."},"balance":{"type":"string","description":"Credit on the key afterwards, in USD."}},"required":["key","keyPrefix","added","balance"]}}}},"400":{"description":"Amount outside 1 to 500 whole USDC. Not charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The key to top up does not exist. Not charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Payment required. x402 v2 requirements are in the PAYMENT-REQUIRED header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"operationId":"creditBalance","summary":"API key balance","description":"The credit left on an API key. Free.","tags":["Credits"],"security":[{"apiKey":[]}],"responses":{"200":{"description":"Balance.","content":{"application/json":{"schema":{"type":"object","properties":{"keyPrefix":{"type":"string"},"balance":{"type":"string","description":"Credit left, in USD."},"createdAt":{"type":"string"},"lastUsedAt":{"type":["string","null"]}},"required":["keyPrefix","balance","createdAt","lastUsedAt"]}}}},"401":{"description":"Missing or unknown API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/status":{"get":{"operationId":"status","summary":"Service status","description":"Whether WhatsApp lookups are being answered right now. Free.","security":[],"responses":{"200":{"description":"Current status.","content":{"application/json":{"schema":{"type":"object","properties":{"whatsapp":{"type":"string","enum":["operational","down"],"description":"Whether WhatsApp lookups are being answered right now."},"checkedAt":{"type":"string"}},"required":["whatsapp","checkedAt"]}}}}}}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"A prepaid wtsp.dev API key (wtsp_…), bought with POST /v1/credits or at wtsp.dev/#keys."}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable machine-readable code, e.g. `invalid_phone`, `payment_required`, `lookup_failed`."},"message":{"type":"string","description":"What went wrong and what to do, in plain words."}},"required":["code","message"]}},"required":["error"]}}}}