{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["tabs","tab","admonition"]},"type":"markdown"},"seo":{"title":"Authentication","description":"Complete developer documentation for the eCommunicate Omnichannel platform. WhatsApp Cloud, WhatsApp Lite, SMS, Live Chat, and Conversations APIs. Send messages, manage templates, configure webhooks, and build customer engagement at scale.","siteUrl":"https://docs.ecommunicate.co.za","lang":"en-ZA","image":"/assets/og-cover.93cb0a29e46afb76d2e2ad760ae643881a756bfe5784b4b0c3553ecb20635632.db81178d.png","keywords":["eCommunicate API","WhatsApp Business API","SMS API","omnichannel messaging","WhatsApp templates","messaging platform","South Africa messaging API","bulk SMS API","two-way SMS","SMS gateway","delivery receipts"],"meta":[{"name":"author","content":"eCommunicate (Pty) Ltd"},{"name":"robots","content":"index, follow"}],"jsonLd":{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://www.ecommunicate.co.za/#organization","name":"eCommunicate","url":"https://www.ecommunicate.co.za/","logo":"https://docs.ecommunicate.co.za/images/logo.png","sameAs":["https://www.ecommunicate.co.za/"],"contactPoint":{"@type":"ContactPoint","email":"support@ecommunicate.co.za","contactType":"customer support"}},{"@type":"WebSite","@id":"https://docs.ecommunicate.co.za/#website","name":"eCommunicate API Documentation","url":"https://docs.ecommunicate.co.za","publisher":{"@id":"https://www.ecommunicate.co.za/#organization"}}]},"llmstxt":{"hide":false,"title":"eCommunicate Omnichannel API","description":"Developer documentation for the eCommunicate Omnichannel platform — WhatsApp Cloud, WhatsApp Lite, SMS, Live Chat, and Conversations APIs.","sections":[{"title":"Guides","includeFiles":["guides/**/*.md"],"excludeFiles":[]},{"title":"Tutorials","includeFiles":["tutorials/**/*.md"],"excludeFiles":[]},{"title":"API Reference","includeFiles":["apis/**/*.yaml"],"excludeFiles":[]},{"title":"Changelog","includeFiles":["changelog.md"],"excludeFiles":[]}],"excludeFiles":[]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"authentication","__idx":0},"children":["Authentication"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Every request to the eCommunicate API requires a ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Developer API key"]}," in the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Authorization"]}," header."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"how-it-works","__idx":1},"children":["How it works"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The API uses a custom ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["apiKey"]}," scheme. Pass your key directly in the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Authorization"]}," header — no ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Bearer"]}," prefix, no Basic auth."]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"cURL","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"bash","header":{"controls":{"copy":{}}},"source":"curl -X GET \"https://api.payless4messaging.com/your-endpoint\" \\\n  -H \"Authorization: a1b2c3d4-e5f6-7890-abcd-ef1234567890\"\n","lang":"bash"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Node.js","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"javascript","header":{"controls":{"copy":{}}},"source":"const API_KEY = process.env.ECOMM_API_KEY;\n\nconst response = await fetch('https://api.payless4messaging.com/your-endpoint', {\n  headers: { 'Authorization': API_KEY },\n});\n","lang":"javascript"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Python","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"python","header":{"controls":{"copy":{}}},"source":"import os\nimport requests\n\nAPI_KEY = os.environ[\"ECOMM_API_KEY\"]\n\nresponse = requests.get(\n    \"https://api.payless4messaging.com/your-endpoint\",\n    headers={\"Authorization\": API_KEY},\n)\n","lang":"python"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Java","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"String API_KEY = System.getenv(\"ECOMM_API_KEY\");\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.payless4messaging.com/your-endpoint\"))\n    .header(\"Authorization\", API_KEY)\n    .GET()\n    .build();\n","lang":"java"},"children":[]}]}]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"api-key-format","__idx":2},"children":["API key format"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Your API key is a standard UUID:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"a1b2c3d4-e5f6-7890-abcd-ef1234567890\n"},"children":[]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"retrieve-your-api-key","__idx":3},"children":["Retrieve your API key"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Use this endpoint to obtain your API key using your account credentials. ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["No existing API key is required"]}," — this is the recommended starting point for new integrations."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"POST /payless4messaging-service/WhatsApp/authenticate/retrieveApiKey\n"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Request body:"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"email\": \"user@example.com\",\n  \"password\": \"your-password\",\n  \"clientRef\": \"CLIENT001\"\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Response:"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"apiKey\": \"a1b2c3d4-e5f6-7890-abcd-ef1234567890\"\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"cURL","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"bash","header":{"controls":{"copy":{}}},"source":"curl -X POST \"https://api.payless4messaging.com/payless4messaging-service/WhatsApp/authenticate/retrieveApiKey\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"email\": \"user@example.com\", \"password\": \"your-password\", \"clientRef\": \"CLIENT001\"}'\n","lang":"bash"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Node.js","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"javascript","header":{"controls":{"copy":{}}},"source":"const response = await fetch(\n  'https://api.payless4messaging.com/payless4messaging-service/WhatsApp/authenticate/retrieveApiKey',\n  {\n    method: 'POST',\n    headers: { 'Content-Type': 'application/json' },\n    body: JSON.stringify({\n      email: 'user@example.com',\n      password: 'your-password',\n      clientRef: 'CLIENT001',\n    }),\n  }\n);\n\nconst { apiKey } = await response.json();\nconsole.log('Your API key:', apiKey);\n","lang":"javascript"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Python","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"python","header":{"controls":{"copy":{}}},"source":"import requests\n\nresponse = requests.post(\n    \"https://api.payless4messaging.com/payless4messaging-service/WhatsApp/authenticate/retrieveApiKey\",\n    json={\n        \"email\": \"user@example.com\",\n        \"password\": \"your-password\",\n        \"clientRef\": \"CLIENT001\",\n    },\n)\n\napi_key = response.json()[\"apiKey\"]\nprint(\"Your API key:\", api_key)\n","lang":"python"},"children":[]}]}]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info","name":"Error response"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If the credentials are invalid, the endpoint returns ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["401"]}," with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{\"error\": \"Invalid credentials\"}"]},". Double-check your email, password, and client reference."]}]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"generate-a-new-key","__idx":4},"children":["Generate a new key"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"POST /payless4messaging-service/WhatsApp/SystemUsers/generateAPIKey\n"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Response:"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"token\": \"f6e5d4c3-b2a1-0987-6543-210fedcba987\"\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"danger","name":"Immediate invalidation"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Generating a new key ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["immediately invalidates"]}," the previous one. All integrations using the old key will return ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["401 Unauthorized"]},". Update all your services before or immediately after regeneration."]}]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"error-responses","__idx":5},"children":["Error responses"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Status"},"children":["Status"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Message"},"children":["Message"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Cause"},"children":["Cause"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Resolution"},"children":["Resolution"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["401"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Unauthorized user"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Missing or invalid API key"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Verify your key — see ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"#troubleshooting-a-401"},"children":["Troubleshooting a 401"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["403"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Forbidden"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Valid key but insufficient permissions"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Contact support to verify your account permissions"]}]}]}]}]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"troubleshooting-a-401","__idx":6},"children":["Troubleshooting a 401"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["401 Unauthorized"]}," means the key the server received is not one it recognises. Before changing any"," ","code, ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["confirm which key your account actually has"]}," — there are two ways to check, and they should"," ","agree."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"1-check-the-key-in-the-web-ui","__idx":7},"children":["1. Check the key in the web UI"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Sign in to the eCommunicate web UI and open your API key settings. This shows the key currently active"," ","on your account, which is the value your integration must send."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"2-check-the-key-via-the-api","__idx":8},"children":["2. Check the key via the API"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Call the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"#retrieve-your-api-key"},"children":["retrieve endpoint"]}," with your account credentials. It requires ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["no"," ","existing API key"]},", so it still works when every other call is returning ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["401"]},":"]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"cURL","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"bash","header":{"controls":{"copy":{}}},"source":"curl -X POST \"https://api.payless4messaging.com/payless4messaging-service/WhatsApp/authenticate/retrieveApiKey\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"email\": \"user@example.com\", \"password\": \"your-password\", \"clientRef\": \"CLIENT001\"}'\n","lang":"bash"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Java","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"String body = \"\"\"\n    {\"email\":\"user@example.com\",\"password\":\"your-password\",\"clientRef\":\"CLIENT001\"}\n    \"\"\";\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.payless4messaging.com\"\n        + \"/payless4messaging-service/WhatsApp/authenticate/retrieveApiKey\"))\n    .header(\"Content-Type\", \"application/json\")\n    .POST(HttpRequest.BodyPublishers.ofString(body))\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\n// 200 → the body carries the current apiKey\n// 401 → the credentials themselves are wrong, not the API key\nSystem.out.println(response.statusCode() + \" \" + response.body());\n","lang":"java"},"children":[]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If this call itself returns ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["401"]}," with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{\"error\": \"Invalid credentials\"}"]},", the problem is your email,"," ","password or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["clientRef"]}," — not your API key."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"3-compare-against-what-youre-sending","__idx":9},"children":["3. Compare against what you're sending"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Once you know the correct key, check the value your integration puts in the header. A valid key is a"," ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["36-character UUID"]},"; any other length means it was truncated or padded between your secret store and"," ","the request."]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Java","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"String apiKey = System.getenv(\"ECOMM_API_KEY\");\n\nif (apiKey == null || apiKey.isBlank()) {\n    throw new IllegalStateException(\"ECOMM_API_KEY is not set\");\n}\napiKey = apiKey.trim();   // strip trailing newlines from files and shell exports\n\n// Safe to log — never log the full key\nlogger.info(\"API key length={} suffix=...{}\",\n    apiKey.length(), apiKey.substring(apiKey.length() - 4));\n","lang":"java"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Node.js","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"javascript","header":{"controls":{"copy":{}}},"source":"const apiKey = (process.env.ECOMM_API_KEY ?? '').trim();\n\nif (!apiKey) throw new Error('ECOMM_API_KEY is not set');\n\n// Safe to log — never log the full key\nconsole.log(`API key length=${apiKey.length} suffix=...${apiKey.slice(-4)}`);\n","lang":"javascript"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Python","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"python","header":{"controls":{"copy":{}}},"source":"api_key = os.environ.get(\"ECOMM_API_KEY\", \"\").strip()\n\nif not api_key:\n    raise RuntimeError(\"ECOMM_API_KEY is not set\")\n\n# Safe to log — never log the full key\nprint(f\"API key length={len(api_key)} suffix=...{api_key[-4:]}\")\n","lang":"python"},"children":[]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"common-causes","__idx":10},"children":["Common causes"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Cause"},"children":["Cause"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Fix"},"children":["Fix"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Authorization"]}," header missing"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Add it to ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["every"]}," request — there is no session or cookie fallback"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Bearer"]}," prefix added"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Pass the key on its own; this API uses a custom ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["apiKey"]}," scheme"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Key was regenerated elsewhere"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Retrieve the current key — ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"#generate-a-new-key"},"children":["regeneration permanently invalidates the old one"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Key belongs to a different client"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Retrieve the key for the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["clientRef"]}," you're integrating against"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Whitespace or newline in the value"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Trim it before sending"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Key copied from a truncated log"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Compare against the UI — a valid key is 36 characters"]}]}]}]}]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info","name":"401 vs 403"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["401"]}," means the key wasn't recognised — verify and fix the key. ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["403"]}," means the key ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["was"]}," recognised"," ","but your account isn't permitted to perform that operation — retrieving the key again won't help."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Still stuck after both checks agree? Contact"," ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"mailto:support@ecommunicate.co.za"},"children":["support@ecommunicate.co.za"]}," with the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["requestId"]}," from the error"," ","response. See ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/guides/error-handling#401-unauthorized"},"children":["Error Handling"]}," for the full response format."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"security-best-practices","__idx":11},"children":["Security best practices"]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"warning","name":"Protect your API key"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Your API key grants full access to your eCommunicate account. Treat it like a password."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"store-keys-securely","__idx":12},"children":["Store keys securely"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Never hardcode your API key. Use environment variables or a secrets manager:"]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Environment variable","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"bash","header":{"controls":{"copy":{}}},"source":"# .env (never commit this file)\nECOMM_API_KEY=a1b2c3d4-e5f6-7890-abcd-ef1234567890\n\n# Access in your code\n# Node.js: process.env.ECOMM_API_KEY\n# Python:  os.environ[\"ECOMM_API_KEY\"]\n# Java:    System.getenv(\"ECOMM_API_KEY\")\n","lang":"bash"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"AWS Secrets Manager","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"javascript","header":{"controls":{"copy":{}}},"source":"import { SecretsManagerClient, GetSecretValueCommand } from '@aws-sdk/client-secrets-manager';\n\nconst client = new SecretsManagerClient({ region: 'af-south-1' });\nconst { SecretString } = await client.send(\n  new GetSecretValueCommand({ SecretId: 'ecomm/api-key' })\n);\nconst API_KEY = JSON.parse(SecretString).ECOMM_API_KEY;\n","lang":"javascript"},"children":[]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"key-rules","__idx":13},"children":["Key rules"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Rule"},"children":["Rule"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Detail"},"children":["Detail"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Server-side only"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Make API calls from your backend, never from browsers or mobile apps"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["HTTPS always"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["All eCommunicate endpoints require HTTPS — never downgrade to HTTP"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Rotate periodically"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Use the generate endpoint to rotate keys on a regular schedule"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Separate environments"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Use different keys for staging and production where possible"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Monitor usage"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Check your Analytics dashboard for unexpected activity"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Restrict access"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Use the User Management endpoints to control who can access your account"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Never log keys"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Ensure your logging framework redacts the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Authorization"]}," header"]}]}]}]}]}]},"headings":[{"value":"Authentication","id":"authentication","depth":1},{"value":"How it works","id":"how-it-works","depth":2},{"value":"API key format","id":"api-key-format","depth":2},{"value":"Retrieve your API key","id":"retrieve-your-api-key","depth":2},{"value":"Generate a new key","id":"generate-a-new-key","depth":2},{"value":"Error responses","id":"error-responses","depth":2},{"value":"Troubleshooting a 401","id":"troubleshooting-a-401","depth":2},{"value":"1. Check the key in the web UI","id":"1-check-the-key-in-the-web-ui","depth":3},{"value":"2. Check the key via the API","id":"2-check-the-key-via-the-api","depth":3},{"value":"3. Compare against what you're sending","id":"3-compare-against-what-youre-sending","depth":3},{"value":"Common causes","id":"common-causes","depth":3},{"value":"Security best practices","id":"security-best-practices","depth":2},{"value":"Store keys securely","id":"store-keys-securely","depth":3},{"value":"Key rules","id":"key-rules","depth":3}],"frontmatter":{"title":"Authentication","description":"How to authenticate with the eCommunicate API using Developer API keys.","seo":{"title":"Authentication"}},"lastModified":"2026-08-11T14:13:51.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/guides/authentication","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}