{"openapi":"3.0.0","paths":{"/v1/public/pricing/options":{"get":{"description":"Anonymous landing-page endpoint that returns customer-visible categories and calculator limits. It does not expose internal pricing rules.","operationId":"PricingController_getPublicCalculatorOptions_v1","parameters":[],"responses":{"200":{"description":"Public calculator configuration.","content":{"application/json":{"schema":{"example":{"currency":"USD","categories":[{"value":"authentication","label":"Authentication"},{"value":"utility","label":"Utility"},{"value":"marketing","label":"Marketing"}],"quantity":{"minimum":1,"maximum":1000000,"unit":"messages_per_month"},"internationalAuthentication":{"supported":true,"availability":"country_dependent"}}}}}}},"summary":"Get public calculator options","tags":["Pricing"]}},"/v1/public/pricing/countries":{"get":{"description":"Anonymous landing-page endpoint returning only the safe country selector fields used by the calculator.","operationId":"PricingController_listPublicCountries_v1","parameters":[],"responses":{"200":{"description":"Active customer-visible pricing countries.","content":{"application/json":{"schema":{"example":[{"countryIso2":"EG","countryName":"Egypt","phoneCode":"+20","marketName":"Egypt","internationalAuthenticationAvailable":true}]}}}}},"summary":"List countries supported by the public calculator","tags":["Pricing"]}},"/v1/public/pricing/calculate":{"get":{"description":"Anonymous landing-page calculator using the active standard Wevlix rate card. Quantity represents projected monthly messages and calculations include tier transitions. The response contains customer-facing totals only and never exposes Meta fees, markup, floors, caps, project overrides, or pricing-version identifiers.","operationId":"PricingController_calculatePublicPrice_v1","parameters":[{"name":"countryIso2","required":true,"in":"query","description":"Two-letter ISO 3166-1 country code.","schema":{"example":"EG","type":"string"}},{"name":"category","required":true,"in":"query","description":"WhatsApp message pricing category.","schema":{"example":"utility","type":"string","enum":["authentication","utility","marketing"]}},{"name":"quantity","required":true,"in":"query","description":"Projected messages for one calendar month. Tier transitions are included in the estimate.","schema":{"minimum":1,"maximum":1000000,"example":10000,"type":"number"}},{"name":"international","required":false,"in":"query","description":"Use the international authentication rate when the selected country supports it. Ignored for other categories.","schema":{"default":false,"example":false,"type":"boolean"}}],"responses":{"200":{"description":"Customer-visible standard pricing estimate.","content":{"application/json":{"schema":{"example":{"generatedAt":"2026-07-17T12:00:00.000Z","estimate":true,"currency":"USD","quantity":10000,"country":{"iso2":"EG","name":"Egypt","phoneCode":"+20"},"market":"Egypt","category":"utility","international":false,"estimatedAverageUnitPrice":"0.006800","estimatedTotal":"68.000000"}}}}}},"summary":"Calculate a public monthly messaging estimate","tags":["Pricing"]}},"/v1/pricing/countries":{"get":{"description":"Returns the customer-visible country and market catalog used for quote and send requests. Use this to populate country selectors or validate countryIso2 values before sending OTPs.","operationId":"PricingController_listCountries_v1","parameters":[],"responses":{"200":{"description":"Countries and markets visible to customers.","content":{"application/json":{"schema":{"example":[{"countryIso2":"{ISO2_COUNTRY_CODE}","countryName":"Example Country","phoneCode":"+1","marketName":"Example Market","isActive":true}]}}}}},"summary":"List supported pricing countries","tags":["Pricing"]}},"/v1/projects/{projectId}/pricing/quote":{"get":{"description":"Calculates the estimated customer-visible price for one or more authentication messages. This endpoint hides Meta costs, markup, floors, caps, and project-specific internal pricing rules.","operationId":"PricingController_quoteProject_v1","parameters":[{"name":"projectId","required":true,"in":"path","schema":{"type":"string"}},{"name":"countryIso2","required":false,"in":"query","schema":{"example":"{ISO2_COUNTRY_CODE}","type":"string"}},{"name":"countryName","required":false,"in":"query","schema":{"example":"Example Country","type":"string"}},{"name":"marketName","required":false,"in":"query","schema":{"example":"Example Market","type":"string"}},{"name":"category","required":false,"in":"query","schema":{"type":"string","enum":["authentication","marketing","utility","service","telegram_gateway_otp"]}},{"name":"quantity","required":false,"in":"query","schema":{"example":1000,"type":"number"}},{"name":"international","required":false,"in":"query","description":"Use international authentication base rate when available.","schema":{"type":"boolean"}}],"responses":{"200":{"description":"A customer-visible pricing quote.","content":{"application/json":{"schema":{"example":{"projectId":"69f84309bc2b9b55a69bd508","pricingVersionId":"a1b2c3d4","currency":"USD","quantity":1,"country":{"iso2":"{ISO2_COUNTRY_CODE}","name":"Example Country","phoneCode":"+1"},"market":"Example Market","category":"AUTHENTICATION","international":false,"currentMonthlyDeliveredCount":120,"estimatedAverageUnitPrice":"0.250000","estimatedTotal":"0.25"}}}}}},"security":[{"bearer":[]}],"summary":"Calculate a project message price. Returns clean customer-visible totals only.","tags":["Pricing"]}},"/v1/public/status":{"get":{"description":"Use this endpoint from monitors or deployment smoke checks to verify the public API is reachable.","operationId":"PublicStatusController_status_v1","parameters":[],"responses":{"200":{"description":"The public API is healthy and reachable.","content":{"application/json":{"schema":{"example":{"service":"wevlix-public-api","status":"ok"}}}}}},"summary":"Check public API availability","tags":["System"]}},"/v1/public/assets/email-logo.png":{"get":{"operationId":"PublicAssetsController_emailLogo_v1","parameters":[],"responses":{"200":{"description":"The public Wevlix email logo."}},"summary":"Get the Wevlix email logo","tags":["System"]}},"/v1/otp/send":{"post":{"description":"Creates a WhatsApp OTP message request. In live mode with a production API key, Wevlix queues a real WhatsApp send through its managed messaging service and requires pricing and balance. An authentication template already submitted to Meta may remain queued for bounded approval refreshes before delivery. In sandbox mode or when using a development key, Wevlix simulates delivery without upstream calls or billing. Use clientMessageId for retry-safe idempotency in your own system.","operationId":"OtpController_send_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendOtpDto"}}}},"responses":{"200":{"description":"OTP request accepted. Live sends are queued for WhatsApp delivery; sandbox/development sends are queued for simulation.","content":{"application/json":{"schema":{"examples":{"live":{"summary":"Live send","value":{"messageId":"0c3e6e70-7c70-4da7-9f2b-7b7f0f25bb5f","clientMessageId":"login_123456","otpMode":"generated","status":"queued","to":"+{country_code}{subscriber_number}","requestedTo":"+{country_code}{subscriber_number}","apiKeyType":"live","executionMode":"live","simulated":false,"pricing":{"currency":"USD","estimatedUnitPrice":"0.250000","estimatedTotal":"0.250000"}}},"sandbox":{"summary":"Sandbox or development-key send","value":{"messageId":"0c3e6e70-7c70-4da7-9f2b-7b7f0f25bb5f","clientMessageId":"login_123456","otpMode":"generated","status":"queued","to":"+{development_country_code}{development_subscriber_number}","requestedTo":"+{country_code}{subscriber_number}","apiKeyType":"development","executionMode":"sandbox","simulated":true,"pricing":{"currency":"USD","estimatedUnitPrice":"0.000000","estimatedTotal":"0.000000"},"sandbox":{"enabled":true,"reason":"development_key"}}}}}}}},"400":{"description":"The request payload is invalid."},"401":{"description":"Missing or invalid API key."},"403":{"description":"OTP sending is not allowed for this API key, the development-key phone allow-list, project WABA state, or project balance."}},"security":[{"api-key":[]}],"summary":"Create an OTP message request in live or sandbox execution mode","tags":["OTP Messages"]}},"/v1/otp/status/{messageId}":{"get":{"description":"Returns the latest lifecycle state for an OTP request. Use this endpoint to power customer support views, retry decisions, and verification UX.","operationId":"OtpController_status_v1","parameters":[{"name":"messageId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Current message status for the OTP request.","content":{"application/json":{"schema":{"example":{"messageId":"0c3e6e70-7c70-4da7-9f2b-7b7f0f25bb5f","clientMessageId":"login_123456","status":"delivered","otpMode":"generated","to":"+{country_code}{subscriber_number}","sentAt":"2026-06-18T08:00:00.000Z","deliveredAt":"2026-06-18T08:00:03.000Z","readAt":null,"failedAt":null,"billedAt":null,"verifiedAt":null,"chargedAmount":"0.25","recovery":null}}}}},"401":{"description":"Missing or invalid API key."},"403":{"description":"The API key does not allow OTP status reads."},"404":{"description":"The requested message was not found."}},"security":[{"api-key":[]}],"summary":"Read OTP message status, delivery, and verification progress","tags":["OTP Messages"]}},"/v1/otp/verify":{"post":{"description":"Checks a six-digit code against the stored hash for a message. Generated and provided-code modes both use this verification endpoint.","operationId":"OtpController_verify_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyOtpDto"}}}},"responses":{"200":{"description":"The OTP code was accepted.","content":{"application/json":{"schema":{"example":{"verified":true,"messageId":"0c3e6e70-7c70-4da7-9f2b-7b7f0f25bb5f","clientMessageId":"login_123456","verifiedAt":"2026-06-18T08:01:00.000Z"}}}}},"400":{"description":"The OTP code or request is invalid."},"401":{"description":"Missing or invalid API key."},"403":{"description":"The API key does not allow OTP verification."}},"security":[{"api-key":[]}],"summary":"Verify an OTP code for a sent WhatsApp message","tags":["OTP Messages"]}},"/v1/telegram/otp/send":{"post":{"description":"The provider is selected by Wevlix administrators. The customer contract, API key scopes, simulation, rate limits, billing, status, and verification endpoints remain unchanged.","operationId":"TelegramOtpController_send_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendOtpDto"}}}},"responses":{"400":{"description":"The request payload is invalid."},"401":{"description":"Missing or invalid API key."},"403":{"description":"Telegram OTP sending is disabled, disallowed by the key, or the project balance is insufficient."}},"security":[{"api-key":[]}],"summary":"Send an OTP through the configured Telegram provider","tags":["Telegram OTP Messages"]}},"/v1/messages/template":{"post":{"description":"Supports authentication, utility, and marketing templates. Approved templates send normally. A template already submitted to Meta but still pending can remain queued while Wevlix performs bounded status refreshes for up to six minutes. Live keys send through Wevlix managed messaging and consume project balance. Development keys and sandbox projects simulate the same queued lifecycle without upstream delivery or balance charges.","operationId":"MessagesController_sendTemplate_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendTemplateMessageDto"}}}},"responses":{"202":{"description":"Template message accepted and queued for delivery."}},"security":[{"api-key":[]}],"summary":"Queue a WhatsApp template message","tags":["Template Messages"]}},"/v1/messages/{messageId}":{"get":{"description":"Returns delivery state and a recovery summary when Wevlix is waiting for Meta template approval or repairing sender and WhatsApp account readiness failures. Failures use stable Wevlix codes and never expose upstream provider details.","operationId":"MessagesController_getStatus_v1","parameters":[{"name":"messageId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Current template message status.","content":{"application/json":{"schema":{"example":{"messageId":"0c3e6e70-7c70-4da7-9f2b-7b7f0f25bb5f","clientMessageId":"order_confirmation_123","status":"queued","to":"+{country_code}{subscriber_number}","executionMode":"live","template":{"id":"9d095bb0-c342-4a3c-8397-a09d646ccffd","name":"order_confirmation","languageCode":"en_US","category":"UTILITY"},"sentAt":null,"deliveredAt":null,"readAt":null,"failedAt":null,"billedAt":null,"failureCode":null,"failureReason":null,"failureRetryable":null,"chargedAmount":null,"recovery":{"state":"waiting","reason":"template_pending","attempt":2,"deadlineAt":"2026-07-16T12:06:00.000Z","nextRetryAt":"2026-07-16T12:01:30.000Z"}}}}}}},"security":[{"api-key":[]}],"summary":"Read a template message delivery status","tags":["Template Messages"]}},"/v1/auth/login":{"post":{"operationId":"setupLogin","tags":["Setup"],"summary":"Login to retrieve a dashboard access token","description":"Use this endpoint only from trusted first-party dashboard or setup tooling. The returned accessToken authorizes project setup calls such as listing project API keys. Do not use this token as the project API key for OTP requests.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","password"],"properties":{"email":{"type":"string","format":"email","example":"user@example.com"},"password":{"type":"string","format":"password","minLength":8,"example":"StrongPass123!"}}}}}},"responses":{"201":{"description":"Login succeeded. Use accessToken as Bearer token for setup endpoints.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string","example":"user_123"},"name":{"type":"string","example":"Jane Developer"},"email":{"type":"string","example":"user@example.com"}}},"accessToken":{"type":"string","example":"eyJhbGciOi..."},"refreshToken":{"type":"string","example":"wvlx_refresh_..."}}}}}}}},"401":{"description":"Email, password, verification, or account state failed."}}}},"/v1/projects/{projectId}/api-keys":{"get":{"operationId":"setupListProjectApiKeys","tags":["Setup"],"summary":"Get a project API key","description":"Returns production API keys for a project the signed-in user can manage. Choose the needed key by id or name, then use rawKey as X-API-Key for project API requests. Legacy hash-only keys may return rawKey as null until rotated in the dashboard.","security":[{"bearer":[]}],"parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Project id from the Wevlix dashboard."}],"responses":{"200":{"description":"Production API keys visible to the signed-in project member.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","example":"Default production key"},"type":{"type":"string","example":"live"},"rawKey":{"type":"string","nullable":true,"example":"wvlx_live_..."},"scopes":{"type":"array","items":{"type":"string"},"example":["otp:send","otp:status","otp:verify"]},"revokedAt":{"type":"string","nullable":true,"example":null},"expiresAt":{"type":"string","nullable":true,"example":null}}}}}}}}},"401":{"description":"Missing or invalid dashboard bearer token."},"403":{"description":"The signed-in user is not allowed to manage project API keys."}}}},"/v1/projects/{projectId}/whatsapp-account/templates":{"get":{"operationId":"setupListProjectWhatsappTemplates","tags":["Setup"],"summary":"List templates available to the project","description":"Returns the project template read model. Use the Wevlix template id from an APPROVED template when calling POST /v1/messages/template. This setup operation uses the dashboard Bearer token, not the project API key.","security":[{"bearer":[]}],"parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Project id from the Wevlix dashboard."},{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"search","in":"query","schema":{"type":"string"},"description":"Search by template name."},{"name":"type","in":"query","schema":{"type":"string","enum":["AUTHENTICATION","UTILITY","MARKETING","SERVICE"]}},{"name":"status","in":"query","schema":{"type":"string","enum":["PENDING","APPROVED","REJECTED","PAUSED","DISABLED"]}}],"responses":{"200":{"description":"Paginated templates with local ids, names, categories, languages, lifecycle state, and Meta approval status."},"401":{"description":"Missing or invalid dashboard bearer token."},"403":{"description":"Project access is required."}}}}},"info":{"title":"Wevlix Messaging API","description":"Integrate production WhatsApp verification, notifications, and approved template messaging with one project-scoped API.\n\n## Start here\n\n1. [Create and configure a project](https://docs.wevlix.com/docs/public#quickstart).\n2. Keep the project API key in your backend or secret manager.\n3. Start in sandbox mode, send a request, and store the returned `messageId`.\n4. Read message status until it reaches a terminal state.\n5. Connect a WhatsApp Business Account, approve templates, fund the project, and switch to live mode.\n\n## Authentication\n\nMessaging endpoints use `X-API-Key`. Dashboard setup operations use a short-lived Bearer access token. These credentials are not interchangeable, and neither belongs in browser or mobile application code.\n\n## Sandbox and development keys\n\nSandbox projects and development keys execute the same validation, persistence, queue, status, and OTP verification flow without contacting the live messaging network or charging project balance. Development keys remain restricted to their configured test recipients.\n\n## Request lifecycle\n\nSend operations return a Wevlix `messageId`. Treat `accepted` and `queued` as asynchronous states. Continue with the matching status endpoint until `delivered`, `read`, or `failed`. Use a unique `clientMessageId` to make retries safe.\n\n## Response contract\n\nEvery JSON response uses the same envelope: `success`, either `data` or `error`, and `meta`. Preserve `meta.requestId` when contacting support.\n\nRead the [integration guide](https://docs.wevlix.com/docs/public) before using the interactive requests below.","version":"1.0","contact":{},"termsOfService":"https://wevlix.com/terms","x-logo":{"url":"/docs/public/assets/wevlix-logo.png","altText":"Wevlix"}},"tags":[{"name":"System","description":"Health and availability checks for public API consumers."},{"name":"OTP Messages","description":"Create generated or provided-code verification requests, follow delivery state, and verify the submitted code."},{"name":"Template Messages","description":"Send approved authentication, utility, and marketing templates, then follow their asynchronous delivery state."},{"name":"Pricing","description":"Customer-visible country and quote endpoints for estimating message costs."},{"name":"Setup","description":"Optional dashboard-authenticated operations for retrieving a project API key before server-to-server integration."}],"servers":[{"url":"https://api.wevlix.com","description":"Primary API"}],"components":{"securitySchemes":{"bearer":{"scheme":"bearer","bearerFormat":"JWT","type":"http","description":"Short-lived dashboard access token. Use only for the optional setup endpoints in this reference."},"api-key":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Project-scoped server credential used by messaging, status, OTP, and project pricing endpoints. Never expose it in browser or mobile code."}},"schemas":{"SendOtpDto":{"type":"object","properties":{"to":{"type":"string","example":"+{country_code}{subscriber_number}","description":"Recipient phone number in E.164 format: +{country_code}{subscriber_number}."},"countryIso2":{"type":"string","example":"{ISO2_COUNTRY_CODE}","description":"Optional validation hint. Wevlix derives the billing country from the E.164 recipient and rejects a mismatch."},"clientMessageId":{"type":"string","example":"login_123456"},"otpMode":{"type":"string","enum":["generated","provided"],"example":"generated","default":"generated","description":"Use generated when Wevlix creates the OTP, or provided when the caller supplies the code."},"code":{"type":"string","example":"123456","description":"Required when otpMode is provided."},"locale":{"type":"string","example":"en"},"international":{"type":"boolean","description":"Use international authentication base rate when available."}},"required":["to"]},"VerifyOtpDto":{"type":"object","properties":{"messageId":{"type":"string","example":"0c3e6e70-7c70-4da7-9f2b-7b7f0f25bb5f"},"code":{"type":"string","example":"123456"},"clientMessageId":{"type":"string","example":"login_123456"}},"required":["messageId","code"]},"SendTemplateMessageDto":{"type":"object","properties":{"to":{"type":"string","example":"+{country_code}{subscriber_number}","description":"Recipient phone number in E.164 format: +{country_code}{subscriber_number}."},"templateId":{"type":"string","format":"uuid","description":"Wevlix template id returned by the project WhatsApp templates API."},"components":{"type":"array","maxItems":20,"items":{"type":"object","additionalProperties":true},"description":"Meta template components and parameters. Omit for templates without variables.","example":[{"type":"body","parameters":[{"type":"text","text":"Taylor"}]}]},"variables":{"type":"array","maxItems":100,"items":{"type":"string","maxLength":4096},"description":"Simple template variable values in placeholder order. Wevlix maps them to YCloud/Meta components. Use components instead for media or advanced buttons; do not send both fields.","example":["Taylor","WVX-1042","Tomorrow"]},"clientMessageId":{"type":"string","example":"order-confirmation-12345","description":"Caller-controlled idempotency identifier for this project."},"countryIso2":{"type":"string","example":"{ISO2_COUNTRY_CODE}","description":"Optional validation hint. Wevlix derives the billing country from the E.164 recipient and rejects a mismatch."},"phoneNumberId":{"type":"string","description":"Optional sender phone-number id from the effective project WABA."}},"required":["to","templateId"]}}},"externalDocs":{"description":"Wevlix integration guide","url":"https://docs.wevlix.com/docs/public"}}