Troubleshooting
Solutions to common issues and step-by-step debugging guides.
API Errors
401 Unauthorized
Your API key is invalid, missing, or expired.
Checklist:
- Verify the Authorization header format:
Bearer rk_test_xxx - Check that the API key has not been revoked in your dashboard
- Ensure you are using the correct key (test vs live mode)
- Confirm there are no extra spaces or characters in the key
# Correct format
curl -H "Authorization: Bearer rk_test_YOUR_KEY" \
https://api.reachscore.co/v1/tests
# Common mistakes:
# Missing "Bearer" prefix
# Using "Api-Key" header instead
# Including quotes around the key in the header value429 Too Many Requests
You have exceeded your rate limit for the current time window.
How to handle:
- Check the
Retry-Afterheader for seconds to wait - Implement exponential backoff in your code
- Use webhooks instead of polling for test results
- Upgrade your plan for higher limits
// Exponential backoff example
async function requestWithRetry(url, options, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const res = await fetch(url, options);
if (res.status === 429) {
const retryAfter = res.headers.get('Retry-After') || Math.pow(2, attempt);
await new Promise(r => setTimeout(r, retryAfter * 1000));
continue;
}
return res;
}
throw new Error('Max retries exceeded');
}400 invalid_url (Webhook Creation)
The webhook URL was rejected due to SSRF protection.
Requirements:
- URL must use HTTPS (HTTP not allowed)
- Cannot point to localhost, 127.0.0.1, or private IPs
- Cannot use internal hostnames or cloud metadata IPs
- Must be a publicly accessible endpoint
Test Issues
Test stuck in "awaiting_email" status
Your test has not received the email within the expected time.
Debugging steps:
- Verify you sent the email to the correct
test_address - Check your sending service logs for delivery errors
- Confirm the
from_addressexactly matches what you specified - Wait up to 5 minutes for email propagation
- Check if your sending IP is blacklisted
Low deliverability score (below 70)
Your emails are failing authentication or triggering spam filters.
Common causes and fixes:
SPF failure
Add your sending service to your SPF record. Check with: dig TXT yourdomain.com
DKIM failure
Ensure DKIM is configured in your email provider and the public key is published in DNS.
DMARC failure
Set up DMARC with p=none first to monitor, then strengthen to quarantine/reject.
High spam score
Avoid spam trigger words, excessive links, or missing unsubscribe headers. Check the spam details in your test results.
Domain Verification
Domain verification failed
The verification check could not find or validate your DNS record.
Troubleshooting:
- Check DNS propagation: Use Google Dig to verify the record is visible globally
- Verify the record format:
Host: _reachscore (or _reachscore.yourdomain.com) Type: TXT Value: reachscore-verify=dom_YOUR_DOMAIN_ID - Wait for propagation: DNS changes can take 24-48 hours
- Check for typos: The verification value must match exactly
Webhook Issues
Webhook deliveries failing
Your webhook endpoint is not receiving events or returning errors.
Checklist:
- Ensure your endpoint returns 2xx status within 30 seconds
- Check your server logs for incoming requests
- Verify the endpoint is publicly accessible (not behind auth/VPN)
- Confirm SSL certificate is valid and not self-signed
- Check the deliveries list in your dashboard for error details
Signature verification failing
The computed signature does not match the header.
Common causes:
- Using the wrong secret (each endpoint has a unique secret)
- JSON serialization differences - use raw request body
- Not including the timestamp in the signed payload
- Framework parsing the body before you can access raw bytes
// Make sure to use the RAW request body, not parsed JSON
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-reachscore-signature'];
const timestamp = req.headers['x-reachscore-timestamp'];
const rawBody = req.body.toString(); // Use raw body
// Compute: HMAC-SHA256(secret, timestamp + "." + rawBody)
});