# Webhook Cron Setup Guide

**Last Updated:** 2026-03-06

Quick setup guide for using external cron services to trigger the HubSpot sync via webhook endpoint.

## Overview

Instead of installing cron on the server, use an external service to call a webhook endpoint hourly. This is ideal when you don't have server access.

## Quick Setup (3 Minutes)

**No server configuration needed!** The token is hardcoded in `v2/config/cron-webhook-config.php`.

### Step 1: Choose External Cron Service

**Recommended: cron-job.org** (free, reliable)

1. **Sign up:** https://cron-job.org (free account)
2. **Create new cron job:**
   - **Title:** "Ordio HubSpot Sync"
   - **URL:** `https://www.ordio.com/v2/api/cron-webhook-sync.php?token=cf5a877749d9c94e4d6c0bfee780d73b`
   - **Schedule:** "Every hour" or `0 * * * *`
   - **Request method:** GET
   - **Timeout:** 600 seconds
   - **Notifications:** Optional (email on failure)

3. **Save and activate**

**Note:** The token (`cf5a877749d9c94e4d6c0bfee780d73b`) is hardcoded in the config file, so no server configuration is needed.

**Alternative Services:**
- **EasyCron:** https://www.easycron.com (free tier: 1 job)
- **Cronitor:** https://cronitor.io (free tier: 5 monitors)
- **GitHub Actions:** See below

### Step 2: Test Webhook

```bash
curl "https://www.ordio.com/v2/api/cron-webhook-sync.php?token=cf5a877749d9c94e4d6c0bfee780d73b"
```

**Success response:**
```json
{
  "success": true,
  "message": "Sync completed successfully",
  "partners_processed": 15,
  "partners_synced": ["AP-20260129-AD2F73", "AP-20260130-BE3G84"],
  "timestamp": "2026-03-06T12:00:00+00:00",
  "errors": []
}
```

**Error responses:**
- `401 Unauthorized` - Invalid or missing token
- `429 Too Many Requests` - Rate limit (max 1 per 5 minutes)
- `500 Internal Server Error` - Server configuration issue

## GitHub Actions Alternative (Recommended)

If you prefer using GitHub Actions (no external service needed):

**The workflow file is already created** - `.github/workflows/hubspot-sync-cron.yml` is included in the repository.

### Add GitHub Secret

1. Go to: **Settings** → **Secrets and variables** → **Actions**
2. Click **New repository secret**
3. Name: `CRON_WEBHOOK_SECRET`
4. Value: `cf5a877749d9c94e4d6c0bfee780d73b` (hardcoded token from config file)
5. Click **Add secret**

See [GITHUB_SECRETS_SETUP.md](GITHUB_SECRETS_SETUP.md) for detailed setup instructions.

### Enable GitHub Actions

1. Go to **Settings** → **Actions** → **General**
2. Under "Workflow permissions", select: **Read and write permissions**
3. Check: **Allow GitHub Actions to create and approve pull requests**

## Monitoring

### Check Webhook Calls

**cron-job.org:**
- Dashboard shows last execution time
- Execution logs show HTTP response codes
- Email notifications on failure (if configured)

**GitHub Actions:**
- Go to **Actions** tab
- View workflow runs and logs

### Verify Sync is Running

1. **Check sync logs** (if you have server access):
   ```bash
   tail -f /var/log/affiliate-sync.log
   ```

2. **Check HubSpot cache timestamp:**
   - Admin dashboard shows "Last sync" timestamp
   - Should update hourly

3. **Manual trigger test:**
   ```bash
   curl "https://www.ordio.com/v2/api/cron-webhook-sync.php?token=cf5a877749d9c94e4d6c0bfee780d73b"
   ```

## Troubleshooting

### 401 Unauthorized

- **Problem:** Token mismatch
- **Solution:** Verify token in URL matches hardcoded token in `v2/config/cron-webhook-config.php` (`cf5a877749d9c94e4d6c0bfee780d73b`)

### 429 Rate Limit

- **Problem:** Webhook called too frequently
- **Solution:** Wait 5 minutes between calls (rate limit is intentional)

### 500 Internal Server Error

- **Problem:** Server configuration issue
- **Solution:** Check PHP error logs, verify sync script exists and is executable

### Webhook Not Being Called

- **Problem:** External cron service not configured correctly
- **Solution:** 
  - Verify URL is correct (including token)
  - Check cron service logs/dashboard
  - Test manually with `curl`

## Security Best Practices

1. **Token is hardcoded:** The token (`cf5a877749d9c94e4d6c0bfee780d73b`) is hardcoded in `v2/config/cron-webhook-config.php` following the same pattern as Slack webhook URL
2. **Rotate token if repo becomes public:** Update hardcoded fallback in config file and update all external cron services
3. **Rate limiting:** Max 1 call per 5 minutes prevents abuse
4. **Monitor webhook calls:** Check for unauthorized access attempts
5. **Use HTTPS only:** Never use HTTP for webhook URLs
6. **GitHub Secret:** For GitHub Actions, use GitHub Secrets (can be different from hardcoded token)

## Related Documentation

- [CRON_INSTALLATION.md](CRON_INSTALLATION.md) - Full installation guide with all methods
- [CRON_SYNC_RUNBOOK.md](CRON_SYNC_RUNBOOK.md) - Operational runbook
- [DEPLOYMENT_CHECKLIST.md](DEPLOYMENT_CHECKLIST.md) - Deployment checklist
