ReachScore Docs

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 value

429 Too Many Requests

You have exceeded your rate limit for the current time window.

How to handle:

  • Check the Retry-After header 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:

  1. Verify you sent the email to the correct test_address
  2. Check your sending service logs for delivery errors
  3. Confirm the from_address exactly matches what you specified
  4. Wait up to 5 minutes for email propagation
  5. 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:

  1. Check DNS propagation: Use Google Dig to verify the record is visible globally
  2. Verify the record format:
    Host: _reachscore (or _reachscore.yourdomain.com)
    Type: TXT
    Value: reachscore-verify=dom_YOUR_DOMAIN_ID
  3. Wait for propagation: DNS changes can take 24-48 hours
  4. 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)
});

Need More Help?