# Create Cron Job Source: https://docs.a1base.com/a1cron/create POST /v1/cron-jobs/{accountId}/create Create a new scheduled task that will execute HTTP requests at specified intervals. ## Path Parameters Your A1Base account ID ## Request Body A descriptive name for your cron job Detailed description of what this cron job does The URL to call when the cron job executes. Must be a valid HTTP/HTTPS URL. HTTP method to use: GET, POST, PUT, DELETE HTTP headers to include with each request. Common headers include Authorization, Content-Type, etc. Example: ```json { "Authorization": "Bearer your-token", "Content-Type": "application/json" } ``` Request body for POST/PUT methods. Must be a string (JSON string if sending JSON). Timezone for schedule execution (e.g., "America/New\_York", "UTC", "Europe/London") Schedule configuration object Type of repetition: `hourly`, `days`, `weeks`, `months`, `years` Frequency of repetition (e.g., 1 = every day, 2 = every 2 days) Time in 24-hour format "HH:MM" (e.g., "09:00", "14:30") Required for weekly schedules. Array of day numbers: * "0" = Sunday * "1" = Monday * "2" = Tuesday * "3" = Wednesday * "4" = Thursday * "5" = Friday * "6" = Saturday How the schedule ends: `never`, `on`, `after` ISO 8601 timestamp when to stop (required if end\_type is "on") Number of occurrences before stopping (required if end\_type is "after") Retry configuration for failed requests Maximum number of retry attempts (0-10) Seconds to wait between retries Maximum seconds to wait for response Webhook URLs for execution notifications URL to call on successful execution URL to call on failed execution Array of tags for organization and filtering Whether the cron job should start active ## Response Returns the created cron job object with generated ID and calculated next run time. ```bash cURL curl -X POST https://api.a1base.com/v1/cron-jobs/{accountId}/create \ -H "X-API-Key: your-api-key" \ -H "X-API-Secret: your-api-secret" \ -H "Content-Type: application/json" \ -d '{ "name": "Daily Sales Report", "description": "Generate comprehensive sales report", "endpoint_url": "https://api.company.com/reports/daily", "method": "POST", "headers": { "Authorization": "Bearer report-token", "Content-Type": "application/json" }, "body": "{\"report_type\": \"sales\", \"format\": \"pdf\"}", "timezone": "America/New_York", "schedule_config": { "repeat_type": "days", "repeat_every": 1, "time": "09:00", "end_type": "never" }, "retry_config": { "max_retries": 3, "retry_delay_seconds": 300, "timeout_seconds": 30 }, "callbacks": { "success_url": "https://webhooks.company.com/cron-success", "failure_url": "https://webhooks.company.com/cron-failure" }, "tags": ["reports", "daily", "sales"], "is_active": true }' ``` ```javascript Node.js const axios = require('axios'); const createCronJob = async () => { const cronJobData = { name: "Daily Sales Report", description: "Generate comprehensive sales report", endpoint_url: "https://api.company.com/reports/daily", method: "POST", headers: { "Authorization": "Bearer report-token", "Content-Type": "application/json" }, body: JSON.stringify({ report_type: "sales", format: "pdf" }), timezone: "America/New_York", schedule_config: { repeat_type: "days", repeat_every: 1, time: "09:00", end_type: "never" }, retry_config: { max_retries: 3, retry_delay_seconds: 300, timeout_seconds: 30 }, callbacks: { success_url: "https://webhooks.company.com/cron-success", failure_url: "https://webhooks.company.com/cron-failure" }, tags: ["reports", "daily", "sales"], is_active: true }; try { const response = await axios.post( 'https://api.a1base.com/v1/cron-jobs/{accountId}/create', cronJobData, { headers: { 'X-API-Key': 'your-api-key', 'X-API-Secret': 'your-api-secret', 'Content-Type': 'application/json' } } ); console.log('Cron job created:', response.data); } catch (error) { console.error('Error:', error.response.data); } }; createCronJob(); ``` ```python Python import requests import json def create_cron_job(): url = "https://api.a1base.com/v1/cron-jobs/{accountId}/create" headers = { "X-API-Key": "your-api-key", "X-API-Secret": "your-api-secret", "Content-Type": "application/json" } data = { "name": "Daily Sales Report", "description": "Generate comprehensive sales report", "endpoint_url": "https://api.company.com/reports/daily", "method": "POST", "headers": { "Authorization": "Bearer report-token", "Content-Type": "application/json" }, "body": json.dumps({ "report_type": "sales", "format": "pdf" }), "timezone": "America/New_York", "schedule_config": { "repeat_type": "days", "repeat_every": 1, "time": "09:00", "end_type": "never" }, "retry_config": { "max_retries": 3, "retry_delay_seconds": 300, "timeout_seconds": 30 }, "callbacks": { "success_url": "https://webhooks.company.com/cron-success", "failure_url": "https://webhooks.company.com/cron-failure" }, "tags": ["reports", "daily", "sales"], "is_active": True } response = requests.post(url, headers=headers, json=data) if response.status_code == 201: print("Cron job created:", response.json()) else: print("Error:", response.status_code, response.json()) create_cron_job() ``` ```json { "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Daily Sales Report", "description": "Generate comprehensive sales report", "endpoint_url": "https://api.company.com/reports/daily", "schedule": "0 9 * * *", "method": "POST", "headers": { "Authorization": "Bearer report-token", "Content-Type": "application/json" }, "body": "{\"report_type\": \"sales\", \"format\": \"pdf\"}", "is_active": true, "timezone": "America/New_York", "repeat_type": "days", "repeat_every": 1, "days_of_week": null, "hours": 9, "minutes": 0, "end_type": "never", "end_date": null, "end_occurrences": null, "max_retries": 3, "retry_delay_seconds": 300, "timeout_seconds": 30, "success_callback_url": "https://webhooks.company.com/cron-success", "failure_callback_url": "https://webhooks.company.com/cron-failure", "tags": ["reports", "daily", "sales"], "next_run_at": "2024-01-26T14:00:00Z", "last_run_at": null, "consecutive_failures": 0, "created_at": "2024-01-25T10:30:00Z", "updated_at": "2024-01-25T10:30:00Z" } } ``` ## Common Schedule Examples ```json { "repeat_type": "days", "repeat_every": 1, "time": "09:00" } ``` ```json { "repeat_type": "hourly", "repeat_every": 2, "time": "00:00" } ``` ```json { "repeat_type": "weeks", "repeat_every": 1, "time": "18:00", "days_of_week": ["1", "2", "3", "4", "5"] } ``` ```json { "repeat_type": "months", "repeat_every": 1, "time": "00:00" } ``` ```json { "repeat_type": "days", "repeat_every": 1, "time": "10:00", "end_type": "after", "end_occurrences": 30 } ``` # Delete Cron Job Source: https://docs.a1base.com/a1cron/delete DELETE /v1/cron-jobs/{accountId}/delete/{cron_job_id} Permanently delete a cron job. This action cannot be undone. ## Path Parameters Your A1Base account ID The unique identifier of the cron job to delete (UUID format) ## Response Returns 204 No Content on successful deletion. Deleting a cron job is permanent and cannot be undone. All associated execution history will also be deleted. ```bash cURL curl -X DELETE "https://api.a1base.com/v1/cron-jobs/{accountId}/delete/550e8400-e29b-41d4-a716-446655440000" \ -H "X-API-Key: your-api-key" \ -H "X-API-Secret: your-api-secret" ``` ```javascript Node.js const axios = require('axios'); const deleteCronJob = async (cronJobId) => { try { const response = await axios.delete( `https://api.a1base.com/v1/cron-jobs/{accountId}/delete/${cronJobId}`, { headers: { 'X-API-Key': 'your-api-key', 'X-API-Secret': 'your-api-secret' } } ); console.log('Cron job deleted successfully'); } catch (error) { console.error('Error:', error.response.data); } }; deleteCronJob('550e8400-e29b-41d4-a716-446655440000'); ``` ```python Python import requests def delete_cron_job(cron_job_id): url = f"https://api.a1base.com/v1/cron-jobs/{{accountId}}/delete/{cron_job_id}" headers = { "X-API-Key": "your-api-key", "X-API-Secret": "your-api-secret" } response = requests.delete(url, headers=headers) if response.status_code == 204: print("Cron job deleted successfully") else: print("Error:", response.status_code, response.json()) delete_cron_job("550e8400-e29b-41d4-a716-446655440000") ``` ```text 204 No Content ``` ## Before Deleting Consider these alternatives before deleting a cron job: Instead of deleting, you can deactivate the cron job: ```json PATCH /v1/cron-jobs/{accountId}/update/{cron_job_id} { "is_active": false } ``` Get the full configuration before deleting: ```bash GET /v1/cron-jobs/{accountId}/details/{cron_job_id} ``` Save the response to recreate the job later if needed. Export execution history before deletion: ```bash GET /v1/cron-jobs/{accountId}/logs/{cron_job_id}?limit=100 ``` ## Error Responses Cron job with the specified ID does not exist ```json { "detail": [ { "loc": ["path", "cron_job_id"], "msg": "Cron job not found", "type": "not_found" } ] } ``` Invalid or missing API credentials ```json { "detail": "Invalid API credentials" } ``` # Examples Source: https://docs.a1base.com/a1cron/examples Real-world examples and patterns for A1Cron # Examples Explore practical examples of how to use A1Cron for various automation scenarios. ## Daily Operations ### Daily Sales Report Generate a PDF report every morning at 9 AM EST: ```json { "name": "Daily Sales Report", "description": "Generates comprehensive sales report for the previous day", "endpoint_url": "https://api.company.com/reports/daily-sales", "method": "POST", "headers": { "Authorization": "Bearer ${REPORT_API_KEY}", "Content-Type": "application/json" }, "body": "{\"report_type\": \"sales\", \"format\": \"pdf\", \"date\": \"yesterday\"}", "timezone": "America/New_York", "schedule_config": { "repeat_type": "days", "repeat_every": 1, "time": "09:00", "end_type": "never" }, "retry_config": { "max_retries": 3, "retry_delay_seconds": 300, "timeout_seconds": 120 }, "callbacks": { "success_url": "https://api.company.com/webhooks/report-generated", "failure_url": "https://api.company.com/webhooks/report-failed" }, "tags": ["reports", "daily", "sales", "production"] } ``` ### Database Backup Nightly database backup at 2 AM: ```json { "name": "Nightly Database Backup", "description": "Backup production database to S3", "endpoint_url": "https://api.company.com/operations/backup", "method": "POST", "headers": { "X-API-Key": "${BACKUP_API_KEY}" }, "body": "{\"database\": \"production\", \"destination\": \"s3\", \"compression\": true}", "timezone": "UTC", "schedule_config": { "repeat_type": "days", "repeat_every": 1, "time": "02:00", "end_type": "never" }, "retry_config": { "max_retries": 5, "retry_delay_seconds": 600, "timeout_seconds": 300 }, "callbacks": { "failure_url": "https://alerts.company.com/critical/backup-failed" }, "tags": ["backup", "database", "critical"] } ``` ## Weekly Operations ### Weekly Team Summary Send team performance summary every Monday at 8 AM: ```json { "name": "Weekly Team Performance", "description": "Email team performance metrics to managers", "endpoint_url": "https://api.company.com/reports/team-weekly", "method": "POST", "headers": { "Content-Type": "application/json", "Authorization": "Bearer ${REPORTS_TOKEN}" }, "body": "{\"teams\": [\"sales\", \"support\", \"engineering\"], \"send_email\": true}", "timezone": "America/Chicago", "schedule_config": { "repeat_type": "weeks", "repeat_every": 1, "time": "08:00", "days_of_week": ["1"], "end_type": "never" }, "tags": ["reports", "weekly", "management"] } ``` ### Weekday Data Sync Sync data between systems every weekday at 6 PM: ```json { "name": "Weekday CRM Sync", "description": "Sync customer data from CRM to data warehouse", "endpoint_url": "https://api.company.com/sync/crm-to-warehouse", "method": "POST", "headers": { "X-Sync-Token": "${SYNC_TOKEN}" }, "body": "{\"mode\": \"incremental\", \"since\": \"last_sync\"}", "timezone": "America/Los_Angeles", "schedule_config": { "repeat_type": "weeks", "repeat_every": 1, "time": "18:00", "days_of_week": ["1", "2", "3", "4", "5"], "end_type": "never" }, "retry_config": { "max_retries": 3, "retry_delay_seconds": 900, "timeout_seconds": 180 }, "tags": ["sync", "crm", "data-warehouse"] } ``` ## Hourly Operations ### API Health Check Monitor API availability every hour: ```json { "name": "Production API Health Check", "description": "Check if production API is responding", "endpoint_url": "https://api.company.com/health", "method": "GET", "timezone": "UTC", "schedule_config": { "repeat_type": "hourly", "repeat_every": 1, "time": "00:00", "end_type": "never" }, "retry_config": { "max_retries": 2, "retry_delay_seconds": 30, "timeout_seconds": 10 }, "callbacks": { "failure_url": "https://alerts.pagerduty.com/webhook/api-down" }, "tags": ["monitoring", "health", "critical"] } ``` ### Cache Refresh Update cache every 2 hours: ```json { "name": "Product Cache Refresh", "description": "Refresh product catalog cache", "endpoint_url": "https://api.company.com/cache/refresh", "method": "POST", "headers": { "X-Cache-Key": "${CACHE_KEY}" }, "body": "{\"cache_type\": \"products\", \"force\": true}", "timezone": "UTC", "schedule_config": { "repeat_type": "hourly", "repeat_every": 2, "time": "00:30", "end_type": "never" }, "tags": ["cache", "products", "performance"] } ``` ## Monthly Operations ### Monthly Billing Process monthly subscriptions on the 1st: ```json { "name": "Monthly Subscription Billing", "description": "Process all active monthly subscriptions", "endpoint_url": "https://api.company.com/billing/process-monthly", "method": "POST", "headers": { "Authorization": "Bearer ${BILLING_API_KEY}", "Content-Type": "application/json" }, "body": "{\"billing_cycle\": \"monthly\", \"retry_failed\": true}", "timezone": "America/New_York", "schedule_config": { "repeat_type": "months", "repeat_every": 1, "time": "04:00", "end_type": "never" }, "retry_config": { "max_retries": 5, "retry_delay_seconds": 3600, "timeout_seconds": 300 }, "callbacks": { "success_url": "https://api.company.com/webhooks/billing-complete", "failure_url": "https://api.company.com/webhooks/billing-failed" }, "tags": ["billing", "monthly", "financial", "critical"] } ``` ### Monthly Report Archive Archive old reports on the 1st of each month: ```json { "name": "Monthly Report Archive", "description": "Move reports older than 90 days to cold storage", "endpoint_url": "https://api.company.com/archive/reports", "method": "POST", "body": "{\"older_than_days\": 90, \"destination\": \"glacier\"}", "timezone": "UTC", "schedule_config": { "repeat_type": "months", "repeat_every": 1, "time": "03:00", "end_type": "never" }, "tags": ["archive", "storage", "maintenance"] } ``` ## Limited Duration Campaigns ### 30-Day Marketing Campaign Send daily campaign emails for 30 days: ```json { "name": "Summer Sale Campaign", "description": "Send daily promotional emails for summer sale", "endpoint_url": "https://api.company.com/campaigns/summer-sale/send", "method": "POST", "headers": { "X-Campaign-ID": "summer-2024" }, "body": "{\"segment\": \"all_subscribers\", \"template\": \"summer_sale_daily\"}", "timezone": "America/New_York", "schedule_config": { "repeat_type": "days", "repeat_every": 1, "time": "10:00", "end_type": "after", "end_occurrences": 30 }, "callbacks": { "success_url": "https://api.company.com/campaigns/webhook/sent" }, "tags": ["campaign", "marketing", "summer-sale", "temporary"] } ``` ### Trial Period Reminders Send reminders during 14-day trial: ```json { "name": "Trial Reminder Sequence", "description": "Send trial reminders on days 3, 7, and 13", "endpoint_url": "https://api.company.com/trials/send-reminder", "method": "POST", "headers": { "Authorization": "Bearer ${TRIAL_API_KEY}" }, "body": "{\"trial_id\": \"${TRIAL_ID}\", \"reminder_type\": \"scheduled\"}", "timezone": "UTC", "schedule_config": { "repeat_type": "days", "repeat_every": 1, "time": "14:00", "end_type": "on", "end_date": "2024-12-31T23:59:59Z" }, "tags": ["trial", "onboarding", "temporary"] } ``` ## Complex Scheduling Patterns ### Business Hours Only Run every 30 minutes during business hours (9 AM - 5 PM weekdays): ```json { "name": "Business Hours Sync", "description": "Sync data every 30 minutes during business hours", "endpoint_url": "https://api.company.com/sync/realtime", "method": "POST", "timezone": "America/New_York", "schedule_config": { "repeat_type": "hourly", "repeat_every": 1, "time": "00:00", "end_type": "never" }, "headers": { "X-Sync-Mode": "business-hours" }, "tags": ["sync", "business-hours"] } ``` For true 30-minute intervals during business hours only, you would need to create multiple cron jobs or implement the logic in your endpoint. ### Quarterly Reports Generate reports on the first day of each quarter: ```json { "name": "Quarterly Financial Report", "description": "Generate comprehensive quarterly financial report", "endpoint_url": "https://api.company.com/reports/quarterly-financial", "method": "POST", "headers": { "Authorization": "Bearer ${FINANCIAL_API_KEY}" }, "body": "{\"report_type\": \"quarterly\", \"include_projections\": true}", "timezone": "America/New_York", "schedule_config": { "repeat_type": "months", "repeat_every": 3, "time": "06:00", "end_type": "never" }, "retry_config": { "max_retries": 5, "retry_delay_seconds": 1800, "timeout_seconds": 600 }, "callbacks": { "success_url": "https://api.company.com/webhooks/quarterly-report-ready" }, "tags": ["reports", "quarterly", "financial", "executive"] } ``` ## Error Handling Examples ### With Exponential Backoff Implement exponential backoff using retry configuration: ```json { "name": "Data Export with Backoff", "description": "Export data with exponential retry delays", "endpoint_url": "https://api.company.com/export/large-dataset", "method": "POST", "timezone": "UTC", "schedule_config": { "repeat_type": "days", "repeat_every": 1, "time": "01:00", "end_type": "never" }, "retry_config": { "max_retries": 5, "retry_delay_seconds": 60, "timeout_seconds": 600 }, "callbacks": { "failure_url": "https://api.company.com/alerts/export-failed" }, "tags": ["export", "data", "large"] } ``` ### With Different Failure Handling Different callbacks for different failure scenarios: ```json { "name": "Critical Payment Processing", "description": "Process pending payments with comprehensive error handling", "endpoint_url": "https://api.company.com/payments/process-pending", "method": "POST", "headers": { "X-Payment-Key": "${PAYMENT_KEY}", "X-Idempotency-Key": "${TIMESTAMP}" }, "timezone": "America/New_York", "schedule_config": { "repeat_type": "hourly", "repeat_every": 1, "time": "00:15", "end_type": "never" }, "retry_config": { "max_retries": 3, "retry_delay_seconds": 300, "timeout_seconds": 120 }, "callbacks": { "success_url": "https://api.company.com/webhooks/payments-processed", "failure_url": "https://alerts.company.com/critical/payment-processing-failed" }, "tags": ["payments", "critical", "financial"] } ``` ## Best Practices Examples ### Using Tags Effectively ```json { "name": "Production Data Sync", "tags": ["production", "sync", "critical", "team:data", "owner:john.doe"] } ``` ### Idempotent Endpoints ```json { "headers": { "X-Idempotency-Key": "cron-${JOB_ID}-${EXECUTION_TIME}" } } ``` ### Environment-Specific Configurations ```json { "name": "[PROD] Daily Cleanup", "endpoint_url": "https://api.production.company.com/cleanup", "tags": ["environment:production", "cleanup", "automated"] } ``` ## Testing Patterns ### Dry Run Mode ```json { "name": "Report Generator - Dry Run", "endpoint_url": "https://api.company.com/reports/generate", "headers": { "X-Dry-Run": "true" }, "body": "{\"mode\": \"test\", \"send_notifications\": false}", "tags": ["test", "dry-run"] } ``` ### Sandbox Environment ```json { "name": "[SANDBOX] Payment Test", "endpoint_url": "https://sandbox.company.com/api/payments/test", "headers": { "X-Environment": "sandbox" }, "tags": ["sandbox", "test", "payments"] } ``` ## Need Help? If you need help implementing any of these patterns or have questions about your specific use case, contact our support team at [pennie@a1base.com](mailto:pennie@a1base.com). # Get Cron Job Details Source: https://docs.a1base.com/a1cron/get-details GET /v1/cron-jobs/{accountId}/details/{cron_job_id} Get comprehensive details about a specific cron job including full configuration and execution history. ## Path Parameters Your A1Base account ID The unique identifier of the cron job (UUID format) ## Response Detailed cron job information Unique identifier for the cron job Name of the cron job Description of what the cron job does The URL that will be called when the cron job executes Cron expression representing the schedule HTTP method used for the request (GET, POST, PUT, DELETE) HTTP headers to include with each request Request body for POST/PUT methods Whether the cron job is currently active Timezone for the cron job execution Type of repetition: hourly, days, weeks, months, years Frequency of repetition (e.g., every 2 days) Array of day numbers (0-6) for weekly schedules Hour component of the scheduled time (0-23) Minute component of the scheduled time (0-59) How the schedule ends: never, on, after ISO 8601 timestamp when the schedule ends (if end\_type is "on") Number of occurrences before ending (if end\_type is "after") Maximum number of retry attempts on failure Seconds to wait between retry attempts Maximum seconds to wait for endpoint response Webhook URL to call on successful execution Webhook URL to call on failed execution Array of tags for organization ISO 8601 timestamp of the next scheduled execution ISO 8601 timestamp of the last execution Number of consecutive failed executions ISO 8601 timestamp of when the cron job was created ISO 8601 timestamp of the last update ```bash cURL curl -X GET "https://api.a1base.com/v1/cron-jobs/{accountId}/details/550e8400-e29b-41d4-a716-446655440000" \ -H "X-API-Key: your-api-key" \ -H "X-API-Secret: your-api-secret" ``` ```javascript Node.js const axios = require('axios'); const getCronJobDetails = async (cronJobId) => { try { const response = await axios.get( `https://api.a1base.com/v1/cron-jobs/{accountId}/details/${cronJobId}`, { headers: { 'X-API-Key': 'your-api-key', 'X-API-Secret': 'your-api-secret' } } ); console.log('Cron job details:', response.data); } catch (error) { console.error('Error:', error.response.data); } }; getCronJobDetails('550e8400-e29b-41d4-a716-446655440000'); ``` ```python Python import requests def get_cron_job_details(cron_job_id): url = f"https://api.a1base.com/v1/cron-jobs/{{accountId}}/details/{cron_job_id}" headers = { "X-API-Key": "your-api-key", "X-API-Secret": "your-api-secret" } response = requests.get(url, headers=headers) if response.status_code == 200: print("Cron job details:", response.json()) else: print("Error:", response.status_code, response.json()) get_cron_job_details("550e8400-e29b-41d4-a716-446655440000") ``` ```json { "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Daily Sales Report", "description": "Generate comprehensive sales report for the previous day", "endpoint_url": "https://api.company.com/reports/daily", "schedule": "0 9 * * *", "method": "POST", "headers": { "Authorization": "Bearer report-api-token", "Content-Type": "application/json" }, "body": "{\"report_type\": \"sales\", \"format\": \"pdf\"}", "is_active": true, "timezone": "America/New_York", "repeat_type": "days", "repeat_every": 1, "days_of_week": null, "hours": 9, "minutes": 0, "end_type": "never", "end_date": null, "end_occurrences": null, "max_retries": 3, "retry_delay_seconds": 300, "timeout_seconds": 30, "success_callback_url": "https://api.company.com/webhooks/report-success", "failure_callback_url": "https://api.company.com/webhooks/report-failure", "tags": ["reports", "daily", "sales"], "next_run_at": "2024-01-26T14:00:00Z", "last_run_at": "2024-01-25T14:00:00Z", "consecutive_failures": 0, "created_at": "2024-01-01T00:00:00Z", "updated_at": "2024-01-20T10:30:00Z" } } ``` # Get Execution Logs Source: https://docs.a1base.com/a1cron/get-logs GET /v1/cron-jobs/{accountId}/logs/{cron_job_id} Retrieve the execution history and logs for a specific cron job. This endpoint provides detailed information about past executions, including success/failure status, response codes, and error messages. ## Path Parameters Your A1Base account ID The unique identifier of the cron job (UUID format) ## Query Parameters Page number for pagination (minimum: 1) Number of items per page (minimum: 1, maximum: 100) Filter by execution status: `success`, `failure`, `error`, `timeout` Filter logs after this date (ISO 8601 format) Example: `2024-01-01T00:00:00Z` Filter logs before this date (ISO 8601 format) Example: `2024-01-31T23:59:59Z` ## Response Array of execution log objects Unique identifier for the execution ID of the cron job that was executed ISO 8601 timestamp of when the job was executed Execution status: `success`, `failure`, `error`, `timeout` HTTP response code from the endpoint (null for timeouts) Response body from the endpoint (truncated to 1KB) Error message if the execution failed Pagination information Current page number Items per page Total number of log entries Total number of pages ```bash cURL curl -X GET "https://api.a1base.com/v1/cron-jobs/{accountId}/logs/550e8400-e29b-41d4-a716-446655440000?page=1&limit=20&status=failure" \ -H "X-API-Key: your-api-key" \ -H "X-API-Secret: your-api-secret" ``` ```javascript Node.js const axios = require('axios'); const getCronJobLogs = async (cronJobId) => { try { const response = await axios.get( `https://api.a1base.com/v1/cron-jobs/{accountId}/logs/${cronJobId}`, { params: { page: 1, limit: 20, status: 'failure', start_date: '2024-01-01T00:00:00Z' }, headers: { 'X-API-Key': 'your-api-key', 'X-API-Secret': 'your-api-secret' } } ); console.log('Execution logs:', response.data); } catch (error) { console.error('Error:', error.response.data); } }; getCronJobLogs('550e8400-e29b-41d4-a716-446655440000'); ``` ```python Python import requests from datetime import datetime, timedelta def get_cron_job_logs(cron_job_id): url = f"https://api.a1base.com/v1/cron-jobs/{{accountId}}/logs/{cron_job_id}" headers = { "X-API-Key": "your-api-key", "X-API-Secret": "your-api-secret" } # Get logs from the last 7 days start_date = (datetime.now() - timedelta(days=7)).isoformat() + "Z" params = { "page": 1, "limit": 20, "status": "failure", "start_date": start_date } response = requests.get(url, headers=headers, params=params) if response.status_code == 200: data = response.json() print(f"Found {data['pagination']['total_items']} log entries") for log in data['data']: print(f"{log['executed_at']}: {log['status']} - {log['response_code']}") else: print("Error:", response.status_code, response.json()) get_cron_job_logs("550e8400-e29b-41d4-a716-446655440000") ``` ```json { "data": [ { "id": "exe_123456789", "cron_job_id": "550e8400-e29b-41d4-a716-446655440000", "executed_at": "2024-01-25T14:00:00Z", "status": "success", "response_code": 200, "response_body": "{\"message\": \"Report generated successfully\"}", "error_message": null }, { "id": "exe_987654321", "cron_job_id": "550e8400-e29b-41d4-a716-446655440000", "executed_at": "2024-01-24T14:00:05Z", "status": "failure", "response_code": 500, "response_body": "{\"error\": \"Database connection failed\"}", "error_message": "Endpoint returned status code 500" }, { "id": "exe_456789123", "cron_job_id": "550e8400-e29b-41d4-a716-446655440000", "executed_at": "2024-01-23T14:00:00Z", "status": "timeout", "response_code": null, "response_body": null, "error_message": "Request timed out after 30 seconds" } ], "pagination": { "page": 1, "limit": 20, "total_items": 3, "total_pages": 1 } } ``` ## Log Analysis Examples ```bash GET /v1/cron-jobs/{accountId}/logs/{cron_job_id}?status=failure&limit=10 ``` Shows the 10 most recent failed executions. ```bash GET /v1/cron-jobs/{accountId}/logs/{cron_job_id}?start_date=2024-01-25T00:00:00Z&end_date=2024-01-25T23:59:59Z ``` Get all executions for a specific day to calculate success rate. ```bash GET /v1/cron-jobs/{accountId}/logs/{cron_job_id}?status=timeout ``` Find all executions that timed out to identify performance issues. ```bash GET /v1/cron-jobs/{accountId}/logs/{cron_job_id}?status=error&limit=50 ``` Analyze error patterns to improve reliability. ## Understanding Status Codes The endpoint returned a 2xx status code The endpoint returned a 4xx or 5xx status code Network error or invalid endpoint URL The request exceeded the configured timeout ## Best Practices 1. **Regular Monitoring**: Check logs daily for critical jobs 2. **Set Up Alerts**: Use failure callbacks to get notified immediately 3. **Analyze Patterns**: Look for time-based failure patterns 4. **Export Important Logs**: Download logs before they expire 5. **Calculate Metrics**: Track success rates and response times ## Log Retention Execution logs are retained for 30 days. Export important logs if you need longer retention. # A1Cron Source: https://docs.a1base.com/a1cron/index Schedule and automate HTTP requests with A1Base's powerful cron job system # A1Cron Welcome to A1Cron, A1Base's comprehensive cron job management system that allows you to schedule and automate HTTP requests with precision and reliability. Learn about A1Cron features and capabilities Get started with your first cron job in minutes Explore the complete API documentation See real-world use cases and patterns ## Key Features * **Hourly**: Run tasks every N hours * **Daily**: Execute at specific times each day * **Weekly**: Schedule on specific days of the week * **Monthly**: Run on the first of each month * **Custom**: Define your own schedule patterns * Automatic retries with configurable delays * Success and failure webhook callbacks * Comprehensive execution logs * Real-time status monitoring * Create, update, and delete jobs via API * Tag-based organization * Active/inactive status control * Manual trigger capability * RESTful API design * Detailed error messages * Timezone support * JSON request/response format ## Common Use Cases * **Automated Reports**: Generate daily, weekly, or monthly reports * **Data Synchronization**: Keep systems in sync with scheduled updates * **Health Checks**: Monitor endpoints and services at regular intervals * **Cleanup Tasks**: Run maintenance operations during off-peak hours * **Notification Systems**: Send scheduled reminders and alerts * **Batch Processing**: Process data in scheduled batches ## Getting Started Obtain your API key and secret from the [A1Base Dashboard](https://a1base.com) Use our [Create endpoint](/a1cron/create) to schedule your first task Track your cron job's performance with our [logging system](/a1cron/get-logs) ## Support Need help? Contact our support team at [pennie@a1base.com](mailto:pennie@a1base.com) or check out our [examples](/a1cron/examples) for common patterns and best practices. # Introduction to A1Cron Source: https://docs.a1base.com/a1cron/introduction Understanding A1Base's cron job scheduling system # Introduction to A1Cron A1Cron is A1Base's powerful cron job management system that enables you to schedule and automate HTTP requests with precision. Whether you need to run daily reports, sync data between systems, or perform regular health checks, A1Cron provides the tools you need to automate these tasks reliably. ## What is A1Cron? A1Cron allows you to: * Schedule HTTP requests to run at specific times and intervals * Monitor execution status and view detailed logs * Configure automatic retries for failed requests * Receive webhook notifications for job outcomes * Organize jobs with tags for easy management ## Core Concepts ### Cron Jobs A cron job is a scheduled task that executes an HTTP request at specified intervals. Each job includes: * **Endpoint URL**: The target URL to call * **Schedule**: When and how often to run * **HTTP Configuration**: Method, headers, and body * **Retry Settings**: How to handle failures * **Callbacks**: Webhooks for success/failure notifications ### Scheduling Options Run tasks every N hours. Perfect for: * Regular data syncs * Cache refreshing * Monitoring checks ```json { "repeat_type": "hourly", "repeat_every": 2, "time": "00:30" } ``` Execute at a specific time each day. Ideal for: * Daily reports * Backup operations * End-of-day processing ```json { "repeat_type": "days", "repeat_every": 1, "time": "09:00" } ``` Run on specific days of the week. Great for: * Weekly summaries * Business day operations * Weekend maintenance ```json { "repeat_type": "weeks", "repeat_every": 1, "time": "08:00", "days_of_week": ["1", "3", "5"] } ``` Execute on the first of each month. Perfect for: * Monthly billing * Report generation * Data archival ```json { "repeat_type": "months", "repeat_every": 1, "time": "00:00" } ``` ### Timezone Support All cron jobs run in the timezone you specify. A1Cron supports all standard timezone identifiers: * `America/New_York` * `Europe/London` * `Asia/Tokyo` * `UTC` Timezone support ensures your jobs run at the correct local time, automatically adjusting for daylight saving time changes. ### Retry Configuration Configure how A1Cron handles failed requests: ```json { "max_retries": 3, "retry_delay_seconds": 60, "timeout_seconds": 30 } ``` * **max\_retries**: Number of retry attempts (0-10) * **retry\_delay\_seconds**: Wait time between retries * **timeout\_seconds**: Maximum time to wait for response ### Webhook Callbacks Get notified about job execution results: ```json { "success_url": "https://your-app.com/webhooks/cron-success", "failure_url": "https://your-app.com/webhooks/cron-failure" } ``` Callbacks receive POST requests with execution details: ```json { "cron_job_id": "550e8400-e29b-41d4-a716-446655440000", "execution_id": "exe_123456", "status": "success", "executed_at": "2024-01-25T14:00:00Z", "response_code": 200, "response_time_ms": 245 } ``` ## Authentication All API requests require authentication headers: ```bash X-API-Key: your-api-key X-API-Secret: your-api-secret ``` Get your credentials from the [A1Base Dashboard](https://a1base.com). ## Base URL All A1Cron endpoints use the base URL: ``` https://api.a1base.com ``` ## Rate Limits * **API Requests**: 1000 requests per hour * **Cron Jobs**: Maximum 100 active jobs per account * **Execution Frequency**: Minimum interval of 1 hour for hourly jobs ## Best Practices Your endpoint should handle being called multiple times safely. Use unique identifiers or timestamps to prevent duplicate processing. Set appropriate timeout values and ensure your endpoints can complete within the configured time limit. Tag your cron jobs by environment, purpose, or team to make management easier as your usage grows. Regularly review execution logs to identify patterns and optimize performance. Use the manual trigger feature to test your cron jobs before enabling scheduled execution. ## Next Steps Create your first cron job Explore the complete API # List Cron Jobs Source: https://docs.a1base.com/a1cron/list GET /v1/cron-jobs/{accountId}/list List all cron jobs for your company with optional filtering and pagination. ## Query Parameters Page number for pagination (minimum: 1) Number of items per page (minimum: 1, maximum: 100) Filter by active status. Set to `true` to show only active jobs, `false` for inactive jobs only. Comma-separated list of tags to filter by. Jobs matching any of the specified tags will be returned. Example: `tags=reports,daily` ## Response Array of cron job objects Unique identifier for the cron job Name of the cron job The URL that will be called when the cron job executes Cron expression representing the schedule HTTP method used for the request Whether the cron job is currently active Timezone for the cron job execution ISO 8601 timestamp of the next scheduled execution ISO 8601 timestamp of the last execution (null if never run) Number of consecutive failed executions ISO 8601 timestamp of when the cron job was created ISO 8601 timestamp of the last update Pagination information Current page number Items per page Total number of cron jobs Total number of pages ```bash cURL curl -X GET "https://api.a1base.com/v1/cron-jobs/{accountId}/list?page=1&limit=20&is_active=true&tags=reports,daily" \ -H "X-API-Key: your-api-key" \ -H "X-API-Secret: your-api-secret" ``` ```javascript Node.js const axios = require('axios'); const listCronJobs = async () => { try { const response = await axios.get( 'https://api.a1base.com/v1/cron-jobs/{accountId}/list', { params: { page: 1, limit: 20, is_active: true, tags: 'reports,daily' }, headers: { 'X-API-Key': 'your-api-key', 'X-API-Secret': 'your-api-secret' } } ); console.log('Cron jobs:', response.data); } catch (error) { console.error('Error:', error.response.data); } }; listCronJobs(); ``` ```python Python import requests def list_cron_jobs(): url = "https://api.a1base.com/v1/cron-jobs/{accountId}/list" headers = { "X-API-Key": "your-api-key", "X-API-Secret": "your-api-secret" } params = { "page": 1, "limit": 20, "is_active": True, "tags": "reports,daily" } response = requests.get(url, headers=headers, params=params) if response.status_code == 200: print("Cron jobs:", response.json()) else: print("Error:", response.status_code, response.json()) list_cron_jobs() ``` ```json { "data": [ { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Daily Sales Report", "endpoint_url": "https://api.company.com/reports/daily", "schedule": "0 9 * * *", "method": "POST", "is_active": true, "timezone": "America/New_York", "next_run_at": "2024-01-26T14:00:00Z", "last_run_at": "2024-01-25T14:00:00Z", "consecutive_failures": 0, "created_at": "2024-01-01T00:00:00Z", "updated_at": "2024-01-25T14:00:00Z" }, { "id": "660f9500-f38c-52e5-b827-557766551111", "name": "Weekly Summary", "endpoint_url": "https://api.company.com/reports/weekly", "schedule": "0 8 * * 1", "method": "GET", "is_active": true, "timezone": "UTC", "next_run_at": "2024-01-29T08:00:00Z", "last_run_at": "2024-01-22T08:00:00Z", "consecutive_failures": 0, "created_at": "2024-01-01T00:00:00Z", "updated_at": "2024-01-22T08:00:00Z" } ], "pagination": { "page": 1, "limit": 20, "total_items": 2, "total_pages": 1 } } ``` # One-Off Cron Jobs Source: https://docs.a1base.com/a1cron/one-off-jobs Schedule tasks to run only once at a specific time # One-Off Cron Jobs Sometimes you need to schedule a task to run just once at a specific time in the future. While A1Cron is primarily designed for recurring schedules, you can achieve one-off execution using a simple workaround with our existing scheduling options. This is a temporary workaround. We're developing enhanced features that will allow AI agents and applications to dynamically schedule one-time tasks more elegantly. Stay tuned for updates! ## Why One-Off Jobs? One-off cron jobs are useful for: * **Scheduled reminders**: Send a reminder email at a specific future time * **Delayed processing**: Process data after a waiting period * **Time-sensitive operations**: Execute tasks at precise moments * **Event-driven scheduling**: Schedule follow-ups based on user actions * **AI agent tasks**: Allow AI systems to schedule future actions dynamically ## Method 1: Using End Occurrences The cleanest approach is to create a cron job that ends after exactly one execution. ### How It Works Set `end_type` to `"after"` and `end_occurrences` to `1`. The job will: 1. Wait until the scheduled time 2. Execute once 3. Automatically deactivate ### Example: Schedule a Task for Tomorrow at 2:30 PM ```bash cURL curl -X POST https://api.a1base.com/v1/cron-jobs/{accountId}/create \ -H "X-API-Key: your-api-key" \ -H "X-API-Secret: your-api-secret" \ -H "Content-Type: application/json" \ -d '{ "name": "Send Follow-up Email", "description": "One-time follow-up email to customer", "endpoint_url": "https://api.example.com/send-followup", "method": "POST", "headers": { "Content-Type": "application/json" }, "body": "{\"customer_id\": \"12345\", \"template\": \"followup_24h\"}", "timezone": "America/New_York", "schedule_config": { "repeat_type": "days", "repeat_every": 1, "time": "14:30", "end_type": "after", "end_occurrences": 1 }, "tags": ["one-off", "followup", "customer-12345"], "is_active": true }' ``` ```javascript Node.js const scheduleOneOffTask = async () => { const response = await axios.post( 'https://api.a1base.com/v1/cron-jobs/{accountId}/create', { name: "Send Follow-up Email", description: "One-time follow-up email to customer", endpoint_url: "https://api.example.com/send-followup", method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ customer_id: "12345", template: "followup_24h" }), timezone: "America/New_York", schedule_config: { repeat_type: "days", repeat_every: 1, time: "14:30", end_type: "after", end_occurrences: 1 }, tags: ["one-off", "followup", "customer-12345"], is_active: true }, { headers: { 'X-API-Key': 'your-api-key', 'X-API-Secret': 'your-api-secret' } } ); console.log(`One-off task scheduled for: ${response.data.next_run_at}`); }; ``` ```python Python import requests from datetime import datetime, timedelta def schedule_one_off_task(): # Calculate tomorrow's date tomorrow = datetime.now() + timedelta(days=1) data = { "name": "Send Follow-up Email", "description": "One-time follow-up email to customer", "endpoint_url": "https://api.example.com/send-followup", "method": "POST", "headers": { "Content-Type": "application/json" }, "body": json.dumps({ "customer_id": "12345", "template": "followup_24h" }), "timezone": "America/New_York", "schedule_config": { "repeat_type": "days", "repeat_every": 1, "time": "14:30", "end_type": "after", "end_occurrences": 1 }, "tags": ["one-off", "followup", "customer-12345"], "is_active": True } response = requests.post( "https://api.a1base.com/v1/cron-jobs/{accountId}/create", headers={ "X-API-Key": "your-api-key", "X-API-Secret": "your-api-secret" }, json=data ) if response.status_code == 201: next_run = response.json()['data']['next_run_at'] print(f"One-off task scheduled for: {next_run}") ``` ## Method 2: Using End Date Alternatively, set an end date shortly after the desired execution time. ### How It Works Set `end_type` to `"on"` with an `end_date` just after your target time. This ensures: 1. The job runs at the scheduled time 2. The schedule expires immediately after ### Example: Schedule for a Specific Date and Time ```json { "name": "Holiday Sale Announcement", "description": "Send holiday sale email on Dec 25 at 9 AM", "endpoint_url": "https://api.example.com/send-announcement", "method": "POST", "timezone": "America/New_York", "schedule_config": { "repeat_type": "days", "repeat_every": 1, "time": "09:00", "end_type": "on", "end_date": "2024-12-25T09:01:00-05:00" }, "tags": ["one-off", "holiday", "announcement"] } ``` When using the end date method, ensure the end\_date is at least 1 minute after your scheduled time to account for any execution delays. ## Practical Examples ### 1. Delayed Task Execution Schedule a task to run in 2 hours: ```javascript const scheduleDelayedTask = async (delayHours = 2) => { const now = new Date(); const runTime = new Date(now.getTime() + (delayHours * 60 * 60 * 1000)); const timeStr = `${runTime.getHours().toString().padStart(2, '0')}:${runTime.getMinutes().toString().padStart(2, '0')}`; const response = await createCronJob({ name: `Delayed Task - ${now.toISOString()}`, endpoint_url: "https://api.example.com/process-delayed", schedule_config: { repeat_type: "days", repeat_every: 1, time: timeStr, end_type: "after", end_occurrences: 1 } }); return response.data; }; ``` ### 2. AI Agent Scheduling Allow an AI agent to schedule a follow-up action: ```python def ai_schedule_followup(user_id, action, delay_minutes): """ AI agent schedules a one-time follow-up action """ run_time = datetime.now() + timedelta(minutes=delay_minutes) time_str = run_time.strftime("%H:%M") cron_data = { "name": f"AI Follow-up: {action}", "description": f"AI-scheduled task for user {user_id}", "endpoint_url": "https://api.example.com/ai/execute-action", "method": "POST", "body": json.dumps({ "user_id": user_id, "action": action, "scheduled_by": "ai_agent" }), "timezone": "UTC", "schedule_config": { "repeat_type": "days", "repeat_every": 1, "time": time_str, "end_type": "after", "end_occurrences": 1 }, "callbacks": { "success_url": "https://api.example.com/ai/action-completed", "failure_url": "https://api.example.com/ai/action-failed" }, "tags": ["ai-scheduled", "one-off", f"user-{user_id}"] } # Create the one-off cron job return create_cron_job(cron_data) ``` ### 3. Event-Driven Scheduling Schedule a task based on user events: ```javascript // When user signs up, schedule a welcome email for 24 hours later app.post('/user/signup', async (req, res) => { const { userId, email } = req.body; // Create user account await createUser({ userId, email }); // Schedule welcome follow-up for tomorrow const tomorrow = new Date(); tomorrow.setDate(tomorrow.getDate() + 1); const timeStr = "10:00"; // 10 AM in user's timezone await scheduleOneOffCron({ name: `Welcome Email - ${userId}`, endpoint_url: "https://api.example.com/emails/send-welcome", method: "POST", body: JSON.stringify({ userId, email }), timezone: getUserTimezone(userId), schedule_config: { repeat_type: "days", repeat_every: 1, time: timeStr, end_type: "after", end_occurrences: 1 }, tags: ["welcome", "one-off", `user-${userId}`] }); res.json({ message: "User created and welcome email scheduled" }); }); ``` ## Best Practices for One-Off Jobs Include timestamps or unique identifiers in job names to distinguish one-off tasks: ```json { "name": "Follow-up Email - User 12345 - 2024-01-25" } ``` Use tags to identify and manage one-off jobs: ```json { "tags": ["one-off", "temporary", "user-12345", "2024-01-25"] } ``` Consider deleting completed one-off jobs to keep your job list clean: ```javascript // In your success webhook handler app.post('/webhooks/cron-success', async (req, res) => { const { cron_job_id, cron_job_name } = req.body; if (cron_job_name.includes('one-off')) { // Delete the completed one-off job await deleteCronJob(cron_job_id); } }); ``` Set up webhook callbacks to confirm one-off tasks complete successfully: ```json { "callbacks": { "success_url": "https://api.example.com/one-off-completed", "failure_url": "https://api.example.com/one-off-failed" } } ``` ## Limitations and Considerations 1. **Minimum Scheduling Time**: Jobs can only be scheduled for future times, not immediate execution 2. **Timezone Awareness**: Ensure you're using the correct timezone for your one-off execution 3. **No Second Precision**: Cron jobs run at minute precision (HH:MM), not exact seconds 4. **Cleanup Required**: One-off jobs remain in your job list after execution unless manually deleted ## Future Improvements We're actively developing enhanced features for one-off scheduling: * **Native one-off job type**: Direct support without workarounds * **Dynamic scheduling API**: Allow AI agents to schedule tasks programmatically * **Immediate execution**: Option to run tasks with minimal delay * **Batch one-off scheduling**: Create multiple one-off tasks in a single request * **Auto-cleanup**: Automatic removal of completed one-off jobs These improvements will make A1Cron even more powerful for AI agents and dynamic applications. ## Summary While A1Cron is designed for recurring schedules, you can effectively create one-off jobs using: 1. **End occurrences method**: Set `end_occurrences: 1` for clean one-time execution 2. **End date method**: Set an end date shortly after the scheduled time Both methods work reliably for scheduling tasks that need to run exactly once at a future time. Choose the method that best fits your use case and remember to tag your one-off jobs appropriately for easy management. For immediate task execution, consider using the [manual trigger](/a1cron/trigger) feature instead of scheduling a one-off job. # Quick Start Source: https://docs.a1base.com/a1cron/quickstart Get up and running with A1Cron in minutes # Quick Start This guide will help you create and manage your first cron job with A1Cron. By the end, you'll have a scheduled task running automatically. ## Prerequisites Before you begin, make sure you have: * An A1Base account * Your API key and secret from the [dashboard](https://a1base.com) * A publicly accessible endpoint URL to call ## Step 1: Create Your First Cron Job Let's create a simple daily cron job that calls your endpoint every morning at 9 AM. ```bash cURL curl -X POST https://api.a1base.com/v1/cron-jobs/{accountId}/create \ -H "X-API-Key: your-api-key" \ -H "X-API-Secret: your-api-secret" \ -H "Content-Type: application/json" \ -d '{ "name": "Daily Morning Report", "description": "Generate daily sales report", "endpoint_url": "https://your-app.com/api/daily-report", "method": "POST", "headers": { "Authorization": "Bearer your-token", "Content-Type": "application/json" }, "body": "{\"report_type\": \"daily\", \"format\": \"pdf\"}", "timezone": "America/New_York", "schedule_config": { "repeat_type": "days", "repeat_every": 1, "time": "09:00", "end_type": "never" }, "retry_config": { "max_retries": 3, "retry_delay_seconds": 300, "timeout_seconds": 30 }, "tags": ["reports", "daily"], "is_active": true }' ``` ```javascript Node.js const axios = require('axios'); const createCronJob = async () => { try { const response = await axios.post( 'https://api.a1base.com/v1/cron-jobs/{accountId}/create', { name: 'Daily Morning Report', description: 'Generate daily sales report', endpoint_url: 'https://your-app.com/api/daily-report', method: 'POST', headers: { 'Authorization': 'Bearer your-token', 'Content-Type': 'application/json' }, body: JSON.stringify({ report_type: 'daily', format: 'pdf' }), timezone: 'America/New_York', schedule_config: { repeat_type: 'days', repeat_every: 1, time: '09:00', end_type: 'never' }, retry_config: { max_retries: 3, retry_delay_seconds: 300, timeout_seconds: 30 }, tags: ['reports', 'daily'], is_active: true }, { headers: { 'X-API-Key': 'your-api-key', 'X-API-Secret': 'your-api-secret', 'Content-Type': 'application/json' } } ); console.log('Cron job created:', response.data); } catch (error) { console.error('Error creating cron job:', error.response.data); } }; createCronJob(); ``` ```python Python import requests import json def create_cron_job(): url = "https://api.a1base.com/v1/cron-jobs/{accountId}/create" headers = { "X-API-Key": "your-api-key", "X-API-Secret": "your-api-secret", "Content-Type": "application/json" } data = { "name": "Daily Morning Report", "description": "Generate daily sales report", "endpoint_url": "https://your-app.com/api/daily-report", "method": "POST", "headers": { "Authorization": "Bearer your-token", "Content-Type": "application/json" }, "body": json.dumps({ "report_type": "daily", "format": "pdf" }), "timezone": "America/New_York", "schedule_config": { "repeat_type": "days", "repeat_every": 1, "time": "09:00", "end_type": "never" }, "retry_config": { "max_retries": 3, "retry_delay_seconds": 300, "timeout_seconds": 30 }, "tags": ["reports", "daily"], "is_active": True } response = requests.post(url, headers=headers, json=data) if response.status_code == 201: print("Cron job created:", response.json()) else: print("Error:", response.status_code, response.json()) create_cron_job() ``` ### Response ```json { "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Daily Morning Report", "description": "Generate daily sales report", "endpoint_url": "https://your-app.com/api/daily-report", "schedule": "0 9 * * *", "method": "POST", "is_active": true, "timezone": "America/New_York", "next_run_at": "2024-01-26T14:00:00Z", "created_at": "2024-01-25T10:30:00Z" } } ``` Save the returned `id` - you'll need it to manage this cron job later. ## Step 2: Verify Your Cron Job Let's check that your cron job was created successfully: ```bash curl -X GET https://api.a1base.com/v1/cron-jobs/{accountId}/details/{cron_job_id} \ -H "X-API-Key: your-api-key" \ -H "X-API-Secret: your-api-secret" ``` ## Step 3: Test with Manual Trigger Before waiting for the scheduled time, test your cron job manually: ```bash curl -X POST https://api.a1base.com/v1/cron-jobs/{accountId}/trigger/{cron_job_id} \ -H "X-API-Key: your-api-key" \ -H "X-API-Secret: your-api-secret" ``` This will immediately execute your cron job and return the result: ```json { "data": { "execution_id": "exe_123456", "status": "success", "response_code": 200, "response_body": "{\"message\": \"Report generated successfully\"}", "executed_at": "2024-01-25T10:35:00Z" } } ``` ## Step 4: Monitor Execution Logs Check the execution history of your cron job: ```bash curl -X GET "https://api.a1base.com/v1/cron-jobs/{accountId}/logs/{cron_job_id}?limit=10" \ -H "X-API-Key: your-api-key" \ -H "X-API-Secret: your-api-secret" ``` ## Common Patterns ### Hourly Health Check ```json { "name": "API Health Check", "endpoint_url": "https://your-api.com/health", "method": "GET", "timezone": "UTC", "schedule_config": { "repeat_type": "hourly", "repeat_every": 1, "time": "00:00" }, "callbacks": { "failure_url": "https://your-app.com/alerts/health-check-failed" } } ``` ### Weekly Report on Business Days ```json { "name": "Weekday Summary", "endpoint_url": "https://your-app.com/api/summary", "method": "POST", "timezone": "America/Chicago", "schedule_config": { "repeat_type": "weeks", "repeat_every": 1, "time": "17:00", "days_of_week": ["1", "2", "3", "4", "5"] } } ``` ### Limited Duration Campaign ```json { "name": "30-Day Campaign", "endpoint_url": "https://your-app.com/api/campaign", "method": "POST", "timezone": "America/Los_Angeles", "schedule_config": { "repeat_type": "days", "repeat_every": 1, "time": "10:00", "end_type": "after", "end_occurrences": 30 } } ``` ## Troubleshooting * Check that `is_active` is set to `true` * Verify the timezone and scheduled time * Ensure your endpoint URL is publicly accessible * Check the execution logs for error messages * Verify your API key and secret are correct * Ensure you're including both headers in your requests * Check that your account ID in the URL is correct * Increase the `timeout_seconds` in your retry configuration * Ensure your endpoint responds within the timeout period * Consider optimizing your endpoint for faster response ## Next Steps Now that you have a working cron job: See more use cases and patterns Deep dive into all endpoints Learn about logs and monitoring Configure success/failure callbacks # Trigger Cron Job Source: https://docs.a1base.com/a1cron/trigger POST /v1/cron-jobs/{accountId}/trigger/{cron_job_id} Manually trigger a cron job execution immediately, regardless of its schedule. This is useful for testing or when you need to run a job outside its normal schedule. ## Path Parameters Your A1Base account ID The unique identifier of the cron job to trigger (UUID format) ## Response Execution result information Unique identifier for this execution Execution status: `success`, `failure`, `error`, `timeout` HTTP response code from the endpoint Response body from the endpoint (truncated to 1KB) ISO 8601 timestamp of when the job was executed Manual triggers bypass the schedule and execute immediately. The job must be active (`is_active: true`) to be triggered. ```bash cURL curl -X POST "https://api.a1base.com/v1/cron-jobs/{accountId}/trigger/550e8400-e29b-41d4-a716-446655440000" \ -H "X-API-Key: your-api-key" \ -H "X-API-Secret: your-api-secret" ``` ```javascript Node.js const axios = require('axios'); const triggerCronJob = async (cronJobId) => { try { const response = await axios.post( `https://api.a1base.com/v1/cron-jobs/{accountId}/trigger/${cronJobId}`, {}, { headers: { 'X-API-Key': 'your-api-key', 'X-API-Secret': 'your-api-secret' } } ); console.log('Execution result:', response.data); } catch (error) { console.error('Error:', error.response.data); } }; triggerCronJob('550e8400-e29b-41d4-a716-446655440000'); ``` ```python Python import requests def trigger_cron_job(cron_job_id): url = f"https://api.a1base.com/v1/cron-jobs/{{accountId}}/trigger/{cron_job_id}" headers = { "X-API-Key": "your-api-key", "X-API-Secret": "your-api-secret" } response = requests.post(url, headers=headers) if response.status_code == 200: print("Execution result:", response.json()) else: print("Error:", response.status_code, response.json()) trigger_cron_job("550e8400-e29b-41d4-a716-446655440000") ``` ```json Success Response { "data": { "execution_id": "exe_123456789", "status": "success", "response_code": 200, "response_body": "{\"message\": \"Report generated successfully\", \"report_id\": \"rpt_98765\"}", "executed_at": "2024-01-25T15:45:00Z" } } ``` ```json Failure Response { "data": { "execution_id": "exe_987654321", "status": "failure", "response_code": 500, "response_body": "{\"error\": \"Database connection failed\"}", "executed_at": "2024-01-25T15:45:00Z" } } ``` ```json Timeout Response { "data": { "execution_id": "exe_456789123", "status": "timeout", "response_code": null, "response_body": "Request timed out after 30 seconds", "executed_at": "2024-01-25T15:45:00Z" } } ``` ## Use Cases Test your endpoint before enabling scheduled execution: 1. Create the cron job with `is_active: false` 2. Trigger it manually to verify it works 3. Update to `is_active: true` when ready Run scheduled tasks outside their normal schedule: * Generate reports on demand * Process data immediately * Respond to user actions When a scheduled execution fails: 1. Check the logs to understand the issue 2. Fix the problem 3. Manually trigger to verify the fix Use manual triggers for initial setup: * Load historical data * Populate caches * Initialize systems ## Important Notes * The cron job must be active (`is_active: true`) to be triggered * Manual triggers count towards your API rate limits * Execution follows the same retry logic as scheduled runs * Webhook callbacks will be triggered as configured ## Error Responses Cron job not found ```json { "detail": "Cron job not found" } ``` Cron job is not active ```json { "detail": "Cron job is not active" } ``` # Update Cron Job Source: https://docs.a1base.com/a1cron/update PATCH /v1/cron-jobs/{accountId}/update/{cron_job_id} Update an existing cron job. All fields are optional - only provide the fields you want to update. ## Path Parameters Your A1Base account ID The unique identifier of the cron job to update (UUID format) ## Request Body All fields are optional. Only include the fields you want to update. New name for the cron job New description New URL to call New HTTP method: GET, POST, PUT, DELETE New HTTP headers (replaces all existing headers) New request body for POST/PUT methods New timezone New schedule configuration (replaces entire schedule) Type of repetition: `hourly`, `days`, `weeks`, `months`, `years` Frequency of repetition Time in 24-hour format "HH:MM" For weekly schedules: array of day numbers ("0"-"6") How the schedule ends: `never`, `on`, `after` ISO 8601 timestamp when to stop Number of occurrences before stopping New retry configuration Maximum retry attempts (0-10) Seconds between retries Response timeout in seconds New webhook URLs Success webhook URL Failure webhook URL New array of tags (replaces all existing tags) Activate or deactivate the cron job ## Response Returns the updated cron job object with all current values. ```bash cURL curl -X PATCH "https://api.a1base.com/v1/cron-jobs/{accountId}/update/550e8400-e29b-41d4-a716-446655440000" \ -H "X-API-Key: your-api-key" \ -H "X-API-Secret: your-api-secret" \ -H "Content-Type: application/json" \ -d '{ "name": "Updated Daily Report", "schedule_config": { "repeat_type": "weeks", "repeat_every": 1, "time": "10:00", "days_of_week": ["1", "3", "5"], "end_type": "never" }, "is_active": false }' ``` ```javascript Node.js const axios = require('axios'); const updateCronJob = async (cronJobId) => { const updates = { name: "Updated Daily Report", schedule_config: { repeat_type: "weeks", repeat_every: 1, time: "10:00", days_of_week: ["1", "3", "5"], end_type: "never" }, is_active: false }; try { const response = await axios.patch( `https://api.a1base.com/v1/cron-jobs/{accountId}/update/${cronJobId}`, updates, { headers: { 'X-API-Key': 'your-api-key', 'X-API-Secret': 'your-api-secret', 'Content-Type': 'application/json' } } ); console.log('Cron job updated:', response.data); } catch (error) { console.error('Error:', error.response.data); } }; updateCronJob('550e8400-e29b-41d4-a716-446655440000'); ``` ```python Python import requests def update_cron_job(cron_job_id): url = f"https://api.a1base.com/v1/cron-jobs/{{accountId}}/update/{cron_job_id}" headers = { "X-API-Key": "your-api-key", "X-API-Secret": "your-api-secret", "Content-Type": "application/json" } updates = { "name": "Updated Daily Report", "schedule_config": { "repeat_type": "weeks", "repeat_every": 1, "time": "10:00", "days_of_week": ["1", "3", "5"], "end_type": "never" }, "is_active": False } response = requests.patch(url, headers=headers, json=updates) if response.status_code == 200: print("Cron job updated:", response.json()) else: print("Error:", response.status_code, response.json()) update_cron_job("550e8400-e29b-41d4-a716-446655440000") ``` ```json { "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Updated Daily Report", "description": "Generate comprehensive sales report", "endpoint_url": "https://api.company.com/reports/daily", "schedule": "0 10 * * 1,3,5", "method": "POST", "headers": { "Authorization": "Bearer report-token", "Content-Type": "application/json" }, "body": "{\"report_type\": \"sales\", \"format\": \"pdf\"}", "is_active": false, "timezone": "America/New_York", "repeat_type": "weeks", "repeat_every": 1, "days_of_week": ["1", "3", "5"], "hours": 10, "minutes": 0, "end_type": "never", "end_date": null, "end_occurrences": null, "max_retries": 3, "retry_delay_seconds": 300, "timeout_seconds": 30, "success_callback_url": "https://webhooks.company.com/cron-success", "failure_callback_url": "https://webhooks.company.com/cron-failure", "tags": ["reports", "daily", "sales"], "next_run_at": null, "last_run_at": "2024-01-25T14:00:00Z", "consecutive_failures": 0, "created_at": "2024-01-01T00:00:00Z", "updated_at": "2024-01-25T15:30:00Z" } } ``` ## Common Update Scenarios ```json { "schedule_config": { "time": "14:30" } } ``` Note: When updating schedule\_config, you must provide all required fields for the schedule type. ```json { "is_active": false } ``` ```json { "headers": { "Authorization": "Bearer new-token", "Content-Type": "application/json", "X-Custom-Header": "value" } } ``` ```json { "tags": ["updated", "production", "critical"] } ``` ```json { "callbacks": { "success_url": "https://new-webhook.com/success", "failure_url": "https://new-webhook.com/failure" } } ``` When updating `schedule_config`, provide the complete configuration object with all required fields for the schedule type, not just the fields you want to change. # Webhooks Source: https://docs.a1base.com/a1cron/webhooks Receive real-time notifications about cron job executions # Webhooks A1Cron supports webhook callbacks to notify your application about cron job execution results in real-time. You can configure separate URLs for successful and failed executions. ## Webhook Configuration When creating or updating a cron job, you can specify webhook URLs in the `callbacks` object: ```json { "callbacks": { "success_url": "https://your-app.com/webhooks/cron-success", "failure_url": "https://your-app.com/webhooks/cron-failure" } } ``` ## Webhook Payload Both success and failure webhooks receive the same payload structure: The unique identifier of the cron job The name of the cron job Unique identifier for this specific execution Execution status: `success`, `failure`, `error`, or `timeout` ISO 8601 timestamp of when the job was executed HTTP response code from the endpoint (null for timeouts) Time taken for the request in milliseconds Response body from the endpoint (truncated to 1KB) Error message if the execution failed (null for success) Which retry attempt this was (0 for first attempt) ISO 8601 timestamp of next retry (null if no more retries) ## Webhook Examples ### Success Webhook Payload ```json { "cron_job_id": "550e8400-e29b-41d4-a716-446655440000", "cron_job_name": "Daily Sales Report", "execution_id": "exe_123456789", "status": "success", "executed_at": "2024-01-25T14:00:00Z", "response_code": 200, "response_time_ms": 245, "response_body": "{\"message\": \"Report generated successfully\", \"report_id\": \"rpt_98765\"}", "error_message": null, "retry_attempt": 0, "next_retry_at": null } ``` ### Failure Webhook Payload ```json { "cron_job_id": "550e8400-e29b-41d4-a716-446655440000", "cron_job_name": "Daily Sales Report", "execution_id": "exe_987654321", "status": "failure", "executed_at": "2024-01-25T14:00:00Z", "response_code": 500, "response_time_ms": 1245, "response_body": "{\"error\": \"Database connection failed\"}", "error_message": "Endpoint returned status code 500", "retry_attempt": 1, "next_retry_at": "2024-01-25T14:05:00Z" } ``` ### Timeout Webhook Payload ```json { "cron_job_id": "550e8400-e29b-41d4-a716-446655440000", "cron_job_name": "Daily Sales Report", "execution_id": "exe_456789123", "status": "timeout", "executed_at": "2024-01-25T14:00:00Z", "response_code": null, "response_time_ms": 30000, "response_body": null, "error_message": "Request timed out after 30 seconds", "retry_attempt": 2, "next_retry_at": "2024-01-25T14:10:00Z" } ``` ## Implementing Webhook Handlers ### Node.js Express Example ```javascript const express = require('express'); const app = express(); app.use(express.json()); // Success webhook handler app.post('/webhooks/cron-success', (req, res) => { const { cron_job_id, cron_job_name, execution_id, response_body, executed_at } = req.body; console.log(`✅ Cron job "${cron_job_name}" executed successfully`); console.log(`Execution ID: ${execution_id}`); console.log(`Response: ${response_body}`); // Process the successful execution // e.g., update database, send notifications, etc. res.status(200).json({ received: true }); }); // Failure webhook handler app.post('/webhooks/cron-failure', (req, res) => { const { cron_job_id, cron_job_name, execution_id, status, error_message, retry_attempt, next_retry_at } = req.body; console.error(`❌ Cron job "${cron_job_name}" failed`); console.error(`Status: ${status}`); console.error(`Error: ${error_message}`); console.error(`Retry attempt: ${retry_attempt}`); if (next_retry_at) { console.log(`Next retry at: ${next_retry_at}`); } else { console.error('No more retries scheduled'); // Send alert to team } res.status(200).json({ received: true }); }); app.listen(3000, () => { console.log('Webhook server listening on port 3000'); }); ``` ### Python Flask Example ```python from flask import Flask, request, jsonify import logging app = Flask(__name__) logging.basicConfig(level=logging.INFO) @app.route('/webhooks/cron-success', methods=['POST']) def handle_cron_success(): data = request.json logging.info(f"✅ Cron job '{data['cron_job_name']}' executed successfully") logging.info(f"Execution ID: {data['execution_id']}") logging.info(f"Response: {data['response_body']}") # Process the successful execution # e.g., update database, send notifications, etc. return jsonify({"received": True}), 200 @app.route('/webhooks/cron-failure', methods=['POST']) def handle_cron_failure(): data = request.json logging.error(f"❌ Cron job '{data['cron_job_name']}' failed") logging.error(f"Status: {data['status']}") logging.error(f"Error: {data['error_message']}") logging.error(f"Retry attempt: {data['retry_attempt']}") if data.get('next_retry_at'): logging.info(f"Next retry at: {data['next_retry_at']}") else: logging.error('No more retries scheduled') # Send alert to team send_alert_to_team(data) return jsonify({"received": True}), 200 def send_alert_to_team(data): # Implement your alerting logic here pass if __name__ == '__main__': app.run(port=3000) ``` ## Webhook Security ### Verify Webhook Signatures A1Cron signs webhook payloads using HMAC-SHA256. Verify the signature to ensure the webhook is from A1Cron: ```javascript const crypto = require('crypto'); function verifyWebhookSignature(payload, signature, secret) { const expectedSignature = crypto .createHmac('sha256', secret) .update(JSON.stringify(payload)) .digest('hex'); return signature === expectedSignature; } app.post('/webhooks/cron-success', (req, res) => { const signature = req.headers['x-a1cron-signature']; const webhookSecret = process.env.WEBHOOK_SECRET; if (!verifyWebhookSignature(req.body, signature, webhookSecret)) { return res.status(401).json({ error: 'Invalid signature' }); } // Process the webhook... }); ``` ### IP Whitelisting For additional security, whitelist A1Cron's webhook IP addresses: * `52.89.214.238` * `34.212.75.30` * `54.218.53.128` ## Webhook Best Practices Return a 2xx status code within 10 seconds. Process heavy operations asynchronously. ```javascript app.post('/webhooks/cron-success', (req, res) => { // Acknowledge receipt immediately res.status(200).json({ received: true }); // Process asynchronously processWebhookAsync(req.body); }); ``` Use the `execution_id` to prevent duplicate processing: ```javascript const processedExecutions = new Set(); app.post('/webhooks/cron-success', (req, res) => { const { execution_id } = req.body; if (processedExecutions.has(execution_id)) { return res.status(200).json({ received: true }); } processedExecutions.add(execution_id); // Process the webhook... }); ``` A1Cron retries failed webhook deliveries up to 3 times with exponential backoff. Log all webhook receipts and failures for debugging: ```javascript app.post('/webhooks/*', (req, res, next) => { console.log({ timestamp: new Date().toISOString(), path: req.path, body: req.body, headers: req.headers }); next(); }); ``` ## Common Use Cases ### Alert on Failures ```javascript app.post('/webhooks/cron-failure', async (req, res) => { const { cron_job_name, error_message, retry_attempt } = req.body; // Send immediate alert for critical jobs if (cron_job_name.includes('critical')) { await sendSlackAlert({ text: `🚨 Critical cron job failed: ${cron_job_name}`, error: error_message, attempt: retry_attempt }); } res.status(200).json({ received: true }); }); ``` ### Track Execution Metrics ```javascript app.post('/webhooks/cron-success', async (req, res) => { const { cron_job_id, response_time_ms, executed_at } = req.body; // Store metrics in time-series database await metricsDB.insert({ job_id: cron_job_id, timestamp: executed_at, duration_ms: response_time_ms, status: 'success' }); res.status(200).json({ received: true }); }); ``` ### Chain Dependent Jobs ```javascript app.post('/webhooks/cron-success', async (req, res) => { const { cron_job_name, response_body } = req.body; // Trigger dependent job after data sync completes if (cron_job_name === 'Data Sync') { const syncResult = JSON.parse(response_body); if (syncResult.records_synced > 0) { await triggerCronJob('Data Processing Job'); } } res.status(200).json({ received: true }); }); ``` ## Testing Webhooks Use [webhook.site](https://webhook.site) to test webhook integration: 1. Go to webhook.site to get a unique URL 2. Use it as your webhook URL when creating a cron job 3. Trigger the cron job manually 4. View the webhook payload on webhook.site Example: ```json { "callbacks": { "success_url": "https://webhook.site/your-unique-id", "failure_url": "https://webhook.site/your-unique-id" } } ``` # Creating Email Addresses Source: https://docs.a1base.com/a1mail/create-email Create an email address to send/receive from using our API The Email API allows you to create custom email addresses on your A1Base account. Get started with our free domains @a101.bot or @a1send.com. ### Request Parameters | Parameter | Type | Required | Description | | ------------- | ------ | -------- | --------------------------------------------------------- | | `address` | string | Yes | The local part of the email address (before the @ symbol) | | `domain_name` | string | Yes | The domain name to use for the email address | ### Endpoint ```bash curl --location 'https://api.a1base.com/v1/emails/{account_id}/create-email' \ --header 'X-API-Key: YOUR_API_KEY' \ --header 'X-API-Secret: YOUR_API_SECRET' \ --header 'Content-Type: application/json' \ --data '{ "address": "jane", "domain_name": "a1send.com" }' ``` Valid Email Addresses: * 5-30 characters long * Only contain letters, numbers, '.', '\_', '-' * Have no consecutive dots, spaces, or commas ### Example Response ```json { "status": "success", } ``` ### Error Responses | Status Code | Description | | ----------- | --------------------------------- | | 400 | Invalid request parameters | | 401 | Invalid API credentials | | 403 | Domain not authorized for account | | 409 | Email address already exists | ## Next Steps After creating your email address, you can: * [Set up a webhook](/a1mail/receiving-email) to receive incoming emails * [Send emails](/a1mail/sending-email) from your new address * [Configure a custom domain](/a1mail/custom-mail-domain/index) for your email addresses We'd love to hear from you! Don't hesitate to reach out to [pennie@a1base.com](mailto:pennie@a1base.com) or [pasha@a1base.com](mailto:pasha@a1base.com) if there's any features you'd like to see or prioritised! # Setup your own custom mail domain on A1Mail Source: https://docs.a1base.com/a1mail/custom-mail-domain/index Instead of using @a1send.com or @a101.bot, setup your own custom email addresses to send and receive emails. ⏰ Estimated setup time: 20min. ### In this guide you will: ### 1. Create a subdomain on your hosting provider for mail: * Log onto your hosting provider (Cloudflare, Namecheap, etc.) * Add a new subdomain called `mail` e.g `mail.yourdomain.com` ### 2. Connect your subdomain to A1Mail * Go to the [email dashboard](https://www.a1base.com/dashboard/email-addresses) * Add in your new subdomain to generate DKIM keys 1 ### 3. Update and test your DNS records * Update the MX record * Add SPF, DKIM, and DMARC records for deliverability and anti-spam * Verify your DNS records are properly configured ### 4. Warm up your new mail domain * Create a new email with your subdomain and send some emails to your new address * Start sending emails using the A1Base API ### Guide Shortcuts: * [Go to the guide for **Namecheap**](#-guide-for-namecheap) * [Go to the guide for **Cloudflare**](#-guide-for-cloudflare) *** # **Namecheap Guide** #### 1. Log into your Namecheap dashboard * Go to [https://www.namecheap.com](https://www.namecheap.com/) * Navigate to **Domain List > Manage** next to `yourdomain.com` * Navigate to **Advanced DNS** *** #### 2. Add an A Record for `mail.example.com` > This points your new mail subdomain, mail.example.com to the server's IP address. * In the **Advanced DNS** tab click **Add New Record** * Select `A Record` and enter the following: ```jsx Host: `@ or mail if your subdomain is mail.example.com` Value: `110.232.112.135` TTL: Automatic ``` *** #### 3. Add an MX Record for email delivery > This tells other mail servers where to deliver email for example.com. * Still in **Advanced DNS,** scroll down to MAIL SETTINGS * Next to "MAIL SETTINGS", select the option "Custom MX" and enter the following: ```jsx Type: `MX Record` Host: `@` Value: `mail.a101.bot` Priority: `10` TTL: Automatic ``` *** #### 4. Update A1Mail Dashboard and get your DKIM values * Go to your [A1Mail dashboard](https://www.a1base.com/dashboard/email-addresses) and navigate to the **Custom Mail Domain** section * Enter your new mail subdomain to get your DKIM keys #### 5. Add the TXT Records for SPF, DKIM, and DMARC > These records are for deliverability and anti-spam * Go back to the **Advanced DNS** tab click **Add New Record**, select `TXT RECORD` for the following: **SPF Record** ```jsx Type: TXT Host: mail Value: v=spf1 ip4:110.232.112.135 a:mail.a101.bot ~all TTL: Automatic ``` **DMARC Record** ```jsx Type: TXT Host: _dmarc Value: v=DMARC1; p=none; rua=mailto:postmaster@subdomain.yourdomain.com TTL: Automatic ``` **DKIM Record** * Copy the host and value from the A1Mail dashboard ```jsx Type: TXT Host: Value: e.g v=DKIM1; h=sha256; k=rsa; t=y; p=asdfgasdfasdf... TTL: Automatic ``` ### Summary: > You should have these records in your Advanced DNS Settings | **Record** | **Type** | **Host** | **Value** | **Priority** | **TTL** | | ---------- | -------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | ------------ | --------- | | SPF | TXT | mail | `v=spf1 ip4:110.232.112.135 a:mail.a101.bot ~all` | — | Automatic | | DMARC | TXT | \_dmarc | `v=DMARC1; p=none; rua=mailto:postmaster@subdomain.yourdomain.com` | — | Automatic | | DKIM | TXT | the domain key we've provided e.g `subdomain._domainkey` | The value we've provided - this will look like: `v=DKIM1; h=sha256; k=rsa; t=y; p=AsDSDGGJGKA...` | — | Automatic | | MX | MX | @ | `mail.a101.bot` | 1 | Automatic | *** # **Cloudflare Guide** #### 1. Log into your Cloudflare dashboard * Go to [https://dash.cloudflare.com](https://dash.cloudflare.com/) * Select your domain from the list * Navigate to the **DNS** tab *** #### 2. Add an A Record for `mail.yourdomain.com` > This points your new mail subdomain to the server's IP address. * Click **Add record** * Select `A` for the Type and enter the following: ```jsx Type: A Name: mail IPv4 address: 110.232.112.135 TTL: Auto Proxy status: DNS only (gray cloud) ``` *** #### 3. Add an MX Record for email delivery > This tells other mail servers where to deliver email for your domain. * Click **Add record** again * Select `MX` for the Type and enter the following: ```jsx Type: MX Name: @ (represents the root domain) Mail server: mail.a101.bot Priority: 10 TTL: Auto ``` *** #### 4. Update A1Mail Dashboard and get your DKIM values * Go to your [A1Mail dashboard](https://www.a1base.com/dashboard/email-addresses) and navigate to the **Custom Mail Domain** section * Enter your new mail subdomain to get your DKIM keys #### 5. Add the TXT Records for SPF, DKIM, and DMARC > These records are for deliverability and anti-spam * Click **Add record** for each of the following TXT records: **SPF Record** ```jsx Type: TXT Name: mail Content: v=spf1 ip4:110.232.112.135 a:mail.a101.bot ~all TTL: Auto ``` **DMARC Record** ```jsx Type: TXT Name: _dmarc Content: v=DMARC1; p=none; rua=mailto:postmaster@yourdomain.com TTL: Auto ``` **DKIM Record** * Copy the host and value from the A1Mail dashboard ```jsx Type: TXT Name: (without your domain) Content: TTL: Auto Proxy status: DNS only (gray cloud) ``` ### Summary: > You should have these records in your Cloudflare DNS settings | **Record** | **Type** | **Name (Host)** | **Content (Value)** | **Priority** | **TTL** | **Proxy Status** | | ---------- | -------- | --------------- | -------------------------------------------------------- | ------------ | ------- | ---------------- | | A | A | mail | `110.232.112.135` | — | Auto | DNS only | | SPF | TXT | mail | `v=spf1 ip4:110.232.112.135 a:mail.a101.bot ~all` | — | Auto | DNS only | | DMARC | TXT | \_dmarc | `v=DMARC1; p=none; rua=mailto:postmaster@yourdomain.com` | — | Auto | DNS only | | DKIM | TXT | from dashboard | from dashboard | — | Auto | DNS only | | MX | MX | @ | `mail.a101.bot` | 10 | Auto | DNS only | > 🔒 **Important**: Make sure all email-related records have the proxy disabled (gray cloud). Email services require direct DNS resolution to function properly. *** # **Test your DNS Settings** After setting up your DNS records, it's essential to verify that they are properly configured. Here's how: #### 1. Check your DNS records * Use a DNS lookup tool (e.g., [MxToolbox](https://mxtoolbox.com/)) to verify your DNS records * Check that your MX, SPF, DKIM, and DMARC records are correctly set up * For detailed instructions, follow our [How to Verify your DNS Settings](verify-dns-settings) guide #### 2. Test email delivery * Send an email to your new custom domain address. By default, all new mail domains will have a `postmaster@yourdomain.com` inbox * If the email is delivered successfully, you can move on to the next step #### Running into issues? > Feel free to reach out to [founders@a1base.com](mailto:founders@a1base.com) directly if you run into any issues during the setup process. *** # **Warm up your new mail domain** After setting up your custom mail domain, you'll need to properly warm it up to ensure good deliverability. Here's how: #### 1. Create a new email with your subdomain * Create an email address using your new subdomain (e.g., `hello@mail.example.com`) * Follow our [Creating Email Addresses guide](api-reference/email/create-email) for detailed instructions #### 2. Send some test emails to your new address * Send emails from your personal accounts (Gmail, Outlook, etc.) to your new address > 💡 **Warming up tips**: New email domains need time to build reputation. Start with low volumes (5-10 emails/day) for the first week, then gradually increase. Avoid sending mass emails immediately after setup. #### 3. Receiving emails * Check that incoming emails are properly delivered to your new address * For more details on receiving and managing emails, see our [Receiving Emails guide](api-reference/email/receiving-email) #### 4. Send emails using the A1Base API * Once your domain is properly warmed up, start sending emails programmatically * Use the A1Base API to send emails from your custom domain address * Follow our [Sending Emails guide](api-reference/email/sending-email) for implementation details Note: * Engage with these emails by replying to them * This helps establish a positive sending reputation for your domain We'd love to hear from you! Don't hesitate to reach out to [pennie@a1base.com](mailto:pennie@a1base.com) or [pasha@a1base.com](mailto:pasha@a1base.com) if there's any features you'd like to see or prioritised! # How to Verify your DNS Settings Source: https://docs.a1base.com/a1mail/custom-mail-domain/verify-dns-settings After setting up your custom mail domain DNS records, it is crucial to verify that they are correctly configured. This guide will walk you through the verification process to ensure your email domain is ready for use with A1Base. ### Recommended Tools: * **Command Line (CLI):** Use `dig` or `nslookup` to verify DNS records directly * **Tools:** * **[MxToolbox](https://mxtoolbox.com/)**: Comprehensive suite of DNS checking tools ## Why DNS Verification Is Important Correctly configured DNS records are essential for: * **Email delivery**: Ensures your emails reach their destination * **Sender reputation**: Helps prevent your emails from being marked as spam * **Security**: Protects your domain from email spoofing and phishing attacks ## What Records to Verify Before using any verification tools, understand what you're looking for: ### 1. MX Records Verify that your MX record points to `mail.a101.bot` with priority `10`: ``` yourdomain.com. IN MX 10 mail.a101.bot. ``` ### 2. SPF Records Verify your SPF record is correctly formatted and includes the A1Mail server: ``` mail.yourdomain.com. IN TXT "v=spf1 ip4:110.232.112.135 a:mail.a101.bot ~all" ``` ### 3. DKIM Records Verify your DKIM record exists and contains the public key provided by A1Mail: ``` 2025_default_mail._domainkey.mail.yourdomain.com. IN TXT "v=DKIM1; h=sha256; k=rsa; t=y; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..." ``` ### 4. DMARC Records Verify your DMARC record is correctly formatted: ``` _dmarc.yourdomain.com. IN TXT "v=DMARC1; p=none; rua=mailto:postmaster@yourdomain.com" ``` *** ## Verification Tools ### Shortcuts: * [Command Line (CLI)](#1-command-line-tools) * [MxToolbox](#2-mxtoolbox) ## 1. Command Line Tools You can use command line tools like `dig` or `nslookup` to verify your DNS records: ```bash # Check MX records dig MX yourdomain.com # Check TXT records (for SPF, DKIM, DMARC) dig TXT mail.yourdomain.com dig TXT _dmarc.yourdomain.com dig TXT 2025_default_mail._domainkey.mail.yourdomain.com ``` *** ## 2. MxToolbox [MxToolbox](https://mxtoolbox.com/) provides comprehensive DNS checking tools: * **For MX records**: Use the [MX Lookup tool](https://mxtoolbox.com/MXLookup.aspx) * Enter: `mail.yourdomain.com` * **For SPF records**: Use the [SPF Record Lookup tool](https://mxtoolbox.com/SPFRecordLookup.aspx) * Enter: `mail.yourdomain.com` (exact host) * **For DKIM records**: Use the [DKIM Lookup tool](https://mxtoolbox.com/dkim.aspx) * Enter: `subdomain._domainkey.yourdomain.com` (You can find this in the A1Mail email dashboard) * **For DMARC records**: Use the [DMARC Lookup tool](https://mxtoolbox.com/DMARC.aspx) * Enter: `_dmarc.yourdomain.com` (exact host) *** ## Troubleshooting Common Issues ### DNS Propagation Delays DNS changes can take up to 48 hours to propagate worldwide. If your verification fails initially, wait a few hours and try again. ### Incorrect Record Format Ensure there are no typos or formatting errors in your DNS records. Even small errors can cause verification to fail. ### Missing Records Verify that all required records (MX, SPF, DKIM, DMARC) are present. Missing any one of these can affect email deliverability. ### Cloudflare Proxy Enabled If using Cloudflare, ensure the proxy (orange cloud) is disabled for all email-related DNS records. Email requires direct DNS resolution. *** ## Need Help? If you're still having trouble verifying your DNS settings, feel free to reach out to our team at [founders@a1base.com](mailto:founders@a1base.com) for assistance. We'd love to hear from you! Don't hesitate to reach out to [pennie@a1base.com](mailto:pennie@a1base.com) or [pasha@a1base.com](mailto:pasha@a1base.com) if there's any features you'd like to see or prioritised! # Quickstart Source: https://docs.a1base.com/a1mail/index Get your AI agents sending and receiving emails in minutes with A1Mail. Follow these simple steps to set up your email integration. ⏰ Estimated setup & testing time: 15min. ## 1. Sign Up and Get API Keys Sign up at [A1Base Dashboard](https://www.a1base.com/) and get your API credentials. * Keep these credentials secure as they'll be used for all API requests ## 2. Create an Email Address You have two options to create your A1Mail email address:
  • Navigate to the Email Dashboard
  • Click "Create New Email Address"
  • Enter your desired email name (e.g., "hello")
  • Select the domain (@a1send.com)
  • Click "Create"
  • Use the API to programmatically create an email address: ```bash curl --location 'https://api.a1base.com/v1/emails/{account_id}/create-email' \ --header 'X-API-Key: YOUR_API_KEY' \ --header 'X-API-Secret: YOUR_API_SECRET' \ --header 'Content-Type: application/json' \ --data '{ "address": "hello", "domain_name": "a1send.com" }' ```
    Note: Email addresses must be between 5 and 30 characters long. ## 3. Test Your New Inbox - Set Up Webhook for Receiving Emails ### Overview To receive incoming emails, you'll need to configure a webhook that will notify your application when new emails arrive. This section guides you through setting up and testing webhooks in your development environment. ### 3.1. Create a Webhook Endpoint First, create an endpoint in your application to receive email notifications. You can use one of our example snippets below or create your own. ```python from flask import Flask, request, jsonify app = Flask(__name__) @app.route('/webhook/email', methods=['POST']) def email_webhook(): # Get the webhook payload data = request.json # Process the incoming email print(f"Received email: {data['subject']} from {data['sender_address']}") # Access specific parts of the email email_id = data.get('email_id') subject = data.get('subject') sender = data.get('sender_address') recipient = data.get('recipient_address') timestamp = data.get('timestamp') raw_email = data.get('raw_email_data') # Your logic here # ... # Return a success response return jsonify({"status": "success"}), 200 if __name__ == '__main__': app.run(debug=True, port=5000) ``` ```javascript const express = require('express'); const app = express(); app.use(express.json()); app.post('/webhook/email', (req, res) => { // Get the webhook payload const data = req.body; // Process the incoming email console.log(`Received email: ${data.subject} from ${data.sender_address}`); // Access specific parts of the email const emailId = data.email_id; const subject = data.subject; const sender = data.sender_address; const recipient = data.recipient_address; const timestamp = data.timestamp; const rawEmail = data.raw_email_data; // Your logic here // ... // Return a success response res.status(200).json({ status: 'success' }); }); app.listen(3000, () => { console.log('Server listening on port 3000'); }); ``` ```javascript // Simple vanilla JavaScript webhook handler // Can be used with any JavaScript framework or serverless function async function handleEmailWebhook(request) { try { // Parse the incoming JSON payload const data = await request.json(); console.log(`Received email: ${data.subject} from ${data.sender_address}`); // Process email data const { email_id, subject, sender_address, recipient_address, timestamp, service, raw_email_data } = data; // Your logic here // ... // Return a success response return new Response(JSON.stringify({ status: 'success' }), { status: 200, headers: { 'Content-Type': 'application/json' } }); } catch (error) { console.error('Error processing webhook:', error); return new Response(JSON.stringify({ status: 'error', message: error.message }), { status: 500, headers: { 'Content-Type': 'application/json' } }); } } ``` ### 3.2 Expose Your Local Webhook Endpoint To receive emails in your inbox, you need to expose your local webhook endpoint to the internet. You can use ngrok to do this. Run the following command in your CLI to start ngrok: ```bash ngrok http 3000 ``` After starting ngrok 1. **Find the forwarding URL** in the ngrok output: ``` Forwarding https://0fcbcda91e79.ngrok.app -> http://localhost:3000 ``` 2. **Create the full webhook URL** by appending your webhook endpoint path: ``` https://0fcbcda91e79.ngrok.app/webhook/email ``` 3. **Use this complete URL** in the A1Mail dashboard webhook settings. ### 3.3 Register Your Webhook in the Dashboard Once you have your webhook URL, you need to register it in the A1Mail dashboard: 1. Log in to your [A1Base Dashboard](https://www.a1base.com/) 2. Navigate to the Email Settings section 3. Find your email address and click "Configure Webhook" 4. Enter your full webhook URL (e.g., `https://0fcbcda91e79.ngrok.app/webhook/email`) 5. Click "Save Changes" ### 3.4 Test Your Webhook Send a test email to your inbox and check if the webhook is receiving the email notifications. ## 4. Send Your First Email Now that you've confirmed your inbox can receive emails, you can start sending emails as that email address. Use the following API call to send your first email: ```bash curl --location 'https://api.a1base.com/v1/emails/{account_id}/send' \ --header 'X-API-Key: YOUR_API_KEY' \ --header 'X-API-Secret: YOUR_API_SECRET' \ --header 'Content-Type: application/json' \ --data '{ "from": "hello@a1send.com", "to": "recipient@example.com", "subject": "My First A1Mail Email", "text": "Hello from my AI agent! This is my first email sent through A1Mail." }' ``` ## 5. In Summary To ensure everything is working correctly: 1. Send a test email to your new A1Mail address from your personal email 2. Check that your webhook receives the incoming email notification 3. Respond to the email using the A1Mail API Now that you've set up basic email functionality, explore more advanced features: * [Sending HTML Emails](/a1mail/sending-email) * [Setting Up Custom Mail Domains](/a1mail/custom-mail-domain/index) * [Email Webhook Security](/api-reference/email/receiving-email) With these steps completed, your AI agent now has a fully functional email inbox! You can send and receive emails programmatically, enabling your agent to communicate with users through email. We'd love to hear from you! Don't hesitate to reach out to [pennie@a1base.com](mailto:pennie@a1base.com) or [pasha@a1base.com](mailto:pasha@a1base.com) if there's any features you'd like to see or prioritised! # Receiving Emails Source: https://docs.a1base.com/a1mail/receiving-email Receive incoming emails through webhooks A1Base can forward incoming emails to your application via webhooks. When an email is received at your A1Base email address, we'll send a POST request to your configured webhook URL with the email details. You can configure your webhook on the [email dashboard here](https://www.a1base.com/dashboard/email-addresses) ⏰ Estimated setup time: 10min. ### In this guide you will: ### 1. Setup a webhook endpoint in your app * Create a simple endpoint to receive email webhooks * Use ngrok to expose your local endpoint to the internet ### 2. Configure webhook URL in A1Mail dashboard * Go to the [email dashboard](https://www.a1base.com/dashboard/email-addresses) * Add your ngrok webhook URL to your A1Mail Dashboard ### 3. Test receiving emails * Send a test email from your personal email address to your A1Mail inbox * View the incoming email data in your webhook endpoint * Parse and process the email contents as needed ## 1. Create a Webhook Endpoint First, create an endpoint in your application to receive email notifications. You can use one of our example snippets below or create your own. ```python from flask import Flask, request, jsonify app = Flask(__name__) @app.route('/webhook/email', methods=['POST']) def email_webhook(): # Get the webhook payload data = request.json # Process the incoming email print(f"Received email: {data['subject']} from {data['sender_address']}") # Access specific parts of the email email_id = data.get('email_id') subject = data.get('subject') sender = data.get('sender_address') recipient = data.get('recipient_address') timestamp = data.get('timestamp') raw_email = data.get('raw_email_data') # Your logic here # ... # Return a success response return jsonify({"status": "success"}), 200 if __name__ == '__main__': app.run(debug=True, port=5000) ``` ```javascript const express = require('express'); const app = express(); app.use(express.json()); app.post('/webhook/email', (req, res) => { // Get the webhook payload const data = req.body; // Process the incoming email console.log(`Received email: ${data.subject} from ${data.sender_address}`); // Access specific parts of the email const emailId = data.email_id; const subject = data.subject; const sender = data.sender_address; const recipient = data.recipient_address; const timestamp = data.timestamp; const rawEmail = data.raw_email_data; // Your logic here // ... // Return a success response res.status(200).json({ status: 'success' }); }); app.listen(3000, () => { console.log('Server listening on port 3000'); }); ``` ```javascript // Simple vanilla JavaScript webhook handler // Can be used with any JavaScript framework or serverless function async function handleEmailWebhook(request) { try { // Parse the incoming JSON payload const data = await request.json(); console.log(`Received email: ${data.subject} from ${data.sender_address}`); // Process email data const { email_id, subject, sender_address, recipient_address, timestamp, service, raw_email_data } = data; // Your logic here // ... // Return a success response return new Response(JSON.stringify({ status: 'success' }), { status: 200, headers: { 'Content-Type': 'application/json' } }); } catch (error) { console.error('Error processing webhook:', error); return new Response(JSON.stringify({ status: 'error', message: error.message }), { status: 500, headers: { 'Content-Type': 'application/json' } }); } } ``` ## 2. Expose Your Local Webhook Endpoint To receive emails in your inbox, you need to expose your local webhook endpoint to the internet. You can use ngrok to do this. Run the following command in your CLI to start ngrok: ```bash ngrok http 3000 ``` After starting ngrok 1. **Find the forwarding URL** in the ngrok output: ``` Forwarding https://0fcbcda91e79.ngrok.app -> http://localhost:3000 ``` 2. **Create the full webhook URL** by appending your webhook endpoint path: ``` https://0fcbcda91e79.ngrok.app/webhook/email ``` 3. **Use this complete URL** in the A1Mail dashboard webhook settings. ## 3. Register Your Webhook in the Dashboard Once you have your webhook URL, you need to register it in the A1Mail dashboard: 1. Log in to your [A1Base Dashboard](https://www.a1base.com/) 2. Navigate to the Email Settings section 3. Find your email address and click "Configure Webhook" 4. Enter your full webhook URL (e.g., `https://0fcbcda91e79.ngrok.app/webhook/email`) 5. Click "Save Changes" ## Webhook Precedence When an email is received, A1Mail will attempt to deliver it to a webhook in the following order: 1. Individual email address webhook 2. Custom domain webhook 3. Default webhook If a webhook is not configured or returns an error, A1Mail will try the next webhook in the precedence list. ![Individual Email Webhook](https://public-a1base-agent-images.s3.us-east-1.amazonaws.com/a1send-webhook.png) ![Custom Domain Webhook](https://public-a1base-agent-images.s3.us-east-1.amazonaws.com/custom-mail-domain-webhook.png) ## 4. Test Your Webhook Send a test email to your inbox and check if the webhook is receiving the email notifications. ## Webhook Payload When an email is received, A1Base will send a POST request to your webhook endpoint with the following JSON payload: ```json { "email_id": "a82b3e6b-dc79-46ad-9284-a166629592e3", "subject": "Email Subject", "sender_address": "sender@example.com", "recipient_address": "your-address@a1send.com", "timestamp": "2025-03-19T10:24:08.46083+00:00", "service": "email", "raw_email_data": "Full email content including headers and body" } ``` ### Payload Fields | Field | Type | Description | | ------------------- | ------ | ----------------------------------------------------- | | `email_id` | string | Unique identifier for the received email | | `subject` | string | Subject line of the email | | `sender_address` | string | Email address of the sender | | `recipient_address` | string | Your A1Base email address that received the message | | `timestamp` | string | ISO 8601 timestamp of when the email was received | | `service` | string | Always "email" for email webhooks | | `raw_email_data` | string | Complete raw email content including headers and body | ## Verifying Signatures on Email Webhooks To ensure the integrity and authenticity of incoming email webhooks, we sign the request using a symmetric-key HMAC (Hash-based Message Authentication Code). This allows you to verify that the webhook was sent by our system and that its payload has not been tampered with. The signature is created using your unique `company_id` as the secret key. You can find your `company_id` in the [A1Mail tab](https://www.a1base.com/dashboard/email-addresses) of your dashboard. ### How it Works 1. **Timestamping**: Each webhook request includes an `x-timestamp` header containing the Unix timestamp (in seconds) of when the request was created. This helps protect against replay attacks. 2. **Signature Creation**: We create a signature string by concatenating the timestamp and the raw JSON body of the request. ``` message_to_sign = + ``` 3. **HMAC-SHA256**: This string is then signed using the HMAC-SHA256 algorithm with your `company_id` as the secret key. 4. **Header Inclusion**: The resulting signature is sent in the `x-signature` header of the request. ### Verification Steps To verify the signature on your end, follow these steps: 1. **Extract Headers**: From the incoming webhook request, extract the `x-timestamp` and `x-signature` headers. 2. **Check the Timestamp**: To mitigate replay attacks, we recommend checking if the `x-timestamp` is recent (e.g., within the last 5 minutes). If the timestamp is too old, you may choose to reject the request. 3. **Prepare the Signature String**: Recreate the `message_to_sign` by concatenating the value from the `x-timestamp` header with the complete, raw body of the POST request. > **Important**: It is critical to use the raw, unmodified request body. Any parsing or modification of the JSON before creating the signature string will result in a mismatch. 4. **Generate Your Expected Signature**: Using your `company_id` as the secret key, compute the HMAC-SHA256 hash of the `message_to_sign` you just created. The output should be a hex-encoded string. 5. **Compare Signatures**: Compare the `x-signature` from the request header with your generated signature. If they match exactly, the webhook is authentic and can be trusted. If they do not match, the request should be discarded. ### Example (Python) ```python import hmac import hashlib import json def verify_webhook_signature(request_body_raw, headers, company_id): """ Verifies the signature of an incoming email webhook. Args: request_body_raw (bytes): The raw, unparsed body of the request. headers (dict): A dictionary of the request headers. company_id (str): Your unique company ID, used as the secret key. Returns: bool: True if the signature is valid, False otherwise. """ received_timestamp = headers.get('x-timestamp') received_signature = headers.get('x-signature') if not received_timestamp or not received_signature: # Necessary headers are missing return False # 1. Prepare the message string message_to_sign = received_timestamp.encode('utf-8') + request_body_raw # 2. Generate the expected signature expected_signature = hmac.new( key=company_id.encode('utf-8'), msg=message_to_sign, digestmod=hashlib.sha256 ).hexdigest() # 3. Compare signatures securely return hmac.compare_digest(expected_signature, received_signature) # --- Usage Example --- # Assuming 'request' is your web framework's request object # company_id = "your_company_id_goes_here" # headers = request.headers # raw_body = request.get_data() # Use a method that gets the raw body # is_valid = verify_webhook_signature(raw_body, headers, company_id) # if is_valid: # print("✅ Signature is valid. Processing webhook.") # # ... process the webhook payload ... # else: # print("❌ Invalid signature. Discarding request.") ``` ## Example Raw Email Data The `raw_email_data` field contains the complete email including headers, which you can parse to extract additional information like: * DKIM signatures * Message ID * Content type * Email body (plain text and HTML versions) * Custom headers We'd love to hear from you! Don't hesitate to reach out to [pennie@a1base.com](mailto:pennie@a1base.com) or [pasha@a1base.com](mailto:pasha@a1base.com) if there's any features you'd like to see or prioritised! # Send Calendar Invites Source: https://docs.a1base.com/a1mail/send-calendar-invites Send calendar invites programmatically through the A1Mail API with just a few lines of code ## Request Parameters The following parameters are used when sending a calendar invite: | Parameter | Type | Required | Description | | ------------------- | ------ | -------- | -------------------------------------------------- | | `sender_address` | string | Yes | Email address that will appear in the "From" field | | `recipient_address` | string | Yes | Email address of the recipient | | `event_title` | string | Yes | Title of the calendar event | | `start_time` | string | Yes | Start time of the event in ISO 8601 format (UTC) | | `end_time` | string | Yes | End time of the event in ISO 8601 format (UTC) | | `organizer_name` | string | Yes | Name of the event organizer | | `method` | string | Yes | Calendar method (REQUEST, CANCEL, REPLY) | | `location` | string | No | Location of the event | | `description` | string | No | Description of the event | | `attendees` | array | No | Array of attendee email addresses | | `mail_headers` | object | No | Additional email headers (sequence, etc.) | ## Code Examples ### Send a Basic Calendar Invite ```bash curl --location 'https://api.a1base.com/v1/emails/{account_id}/send-calendar-invite' \ --header 'X-API-Key: YOUR_API_KEY' \ --header 'X-API-Secret: YOUR_API_SECRET' \ --header 'Content-Type: application/json' \ --data-raw '{ "sender_address": "sender@example.com", "recipient_address": "recipient@example.com", "event_title": "Team Meeting", "start_time": "2024-06-10T10:00:00Z", "end_time": "2024-06-10T11:00:00Z", "organizer_name": "Alice Smith", "method": "REQUEST" }' ``` ### Send a Detailed Calendar Invite ```bash curl --location 'https://api.a1base.com/v1/emails/{account_id}/send-calendar-invite' \ --header 'X-API-Key: YOUR_API_KEY' \ --header 'X-API-Secret: YOUR_API_SECRET' \ --header 'Content-Type: application/json' \ --data-raw '{ "sender_address": "sender@example.com", "recipient_address": "recipient@example.com", "event_title": "Team Meeting", "start_time": "2024-06-10T10:00:00Z", "end_time": "2024-06-10T11:00:00Z", "organizer_name": "Alice Smith", "method": "REQUEST", "location": "Conference Room 1", "description": "Monthly team sync-up", "attendees": ["recipient@example.com", "pennie@a1base.com"], "mail_headers": { "sequence": 0 } }' ``` ### Cancel a Calendar Event ```bash curl --location 'https://api.a1base.com/v1/emails/{account_id}/send-calendar-invite' \ --header 'X-API-Key: YOUR_API_KEY' \ --header 'X-API-Secret: YOUR_API_SECRET' \ --header 'Content-Type: application/json' \ --data-raw '{ "sender_address": "sender@example.com", "recipient_address": "recipient@example.com", "event_title": "Team Meeting", "start_time": "2024-06-10T10:00:00Z", "end_time": "2024-06-10T11:00:00Z", "organizer_name": "Alice Smith", "method": "CANCEL", "location": "Conference Room 1", "description": "Meeting has been cancelled", "attendees": ["recipient@example.com", "pennie@a1base.com"], "mail_headers": { "sequence": 1 } }' ``` ### Send a Basic Calendar Invite ```python import requests import json url = "https://api.a1base.com/v1/emails/{account_id}/send-calendar-invite" headers = { 'X-API-Key': 'YOUR_API_KEY', 'X-API-Secret': 'YOUR_API_SECRET', 'Content-Type': 'application/json' } data = { "sender_address": "sender@example.com", "recipient_address": "recipient@example.com", "event_title": "Team Meeting", "start_time": "2024-06-10T10:00:00Z", "end_time": "2024-06-10T11:00:00Z", "organizer_name": "Alice Smith", "method": "REQUEST" } response = requests.post(url, headers=headers, data=json.dumps(data)) print(response.json()) ``` ### Send a Detailed Calendar Invite ```python import requests import json url = "https://api.a1base.com/v1/emails/{account_id}/send-calendar-invite" headers = { 'X-API-Key': 'YOUR_API_KEY', 'X-API-Secret': 'YOUR_API_SECRET', 'Content-Type': 'application/json' } data = { "sender_address": "sender@example.com", "recipient_address": "recipient@example.com", "event_title": "Team Meeting", "start_time": "2024-06-10T10:00:00Z", "end_time": "2024-06-10T11:00:00Z", "organizer_name": "Alice Smith", "method": "REQUEST", "location": "Conference Room 1", "description": "Monthly team sync-up", "attendees": ["recipient@example.com", "pennie@a1base.com"], "mail_headers": { "sequence": 0 } } response = requests.post(url, headers=headers, data=json.dumps(data)) print(response.json()) ``` ### Cancel a Calendar Event ```python import requests import json url = "https://api.a1base.com/v1/emails/{account_id}/send-calendar-invite" headers = { 'X-API-Key': 'YOUR_API_KEY', 'X-API-Secret': 'YOUR_API_SECRET', 'Content-Type': 'application/json' } data = { "sender_address": "sender@example.com", "recipient_address": "recipient@example.com", "event_title": "Team Meeting", "start_time": "2024-06-10T10:00:00Z", "end_time": "2024-06-10T11:00:00Z", "organizer_name": "Alice Smith", "method": "CANCEL", "location": "Conference Room 1", "description": "Meeting has been cancelled", "attendees": ["recipient@example.com", "pennie@a1base.com"], "mail_headers": { "sequence": 1 } } response = requests.post(url, headers=headers, data=json.dumps(data)) print(response.json()) ``` ### Send a Basic Calendar Invite ```javascript const axios = require('axios'); const url = 'https://api.a1base.com/v1/emails/{account_id}/send-calendar-invite'; const headers = { 'X-API-Key': 'YOUR_API_KEY', 'X-API-Secret': 'YOUR_API_SECRET', 'Content-Type': 'application/json' }; const data = { sender_address: 'sender@example.com', recipient_address: 'recipient@example.com', event_title: 'Team Meeting', start_time: '2024-06-10T10:00:00Z', end_time: '2024-06-10T11:00:00Z', organizer_name: 'Alice Smith', method: 'REQUEST' }; axios.post(url, data, { headers }) .then(response => console.log(response.data)) .catch(error => console.error('Error:', error)); ``` ### Send a Detailed Calendar Invite ```javascript const axios = require('axios'); const url = 'https://api.a1base.com/v1/emails/{account_id}/send-calendar-invite'; const headers = { 'X-API-Key': 'YOUR_API_KEY', 'X-API-Secret': 'YOUR_API_SECRET', 'Content-Type': 'application/json' }; const data = { sender_address: 'sender@example.com', recipient_address: 'recipient@example.com', event_title: 'Team Meeting', start_time: '2024-06-10T10:00:00Z', end_time: '2024-06-10T11:00:00Z', organizer_name: 'Alice Smith', method: 'REQUEST', location: 'Conference Room 1', description: 'Monthly team sync-up', attendees: ['recipient@example.com', 'pennie@a1base.com'], mail_headers: { sequence: 0 } }; axios.post(url, data, { headers }) .then(response => console.log(response.data)) .catch(error => console.error('Error:', error)); ``` ### Cancel a Calendar Event ```javascript const axios = require('axios'); const url = 'https://api.a1base.com/v1/emails/{account_id}/send-calendar-invite'; const headers = { 'X-API-Key': 'YOUR_API_KEY', 'X-API-Secret': 'YOUR_API_SECRET', 'Content-Type': 'application/json' }; const data = { sender_address: 'sender@example.com', recipient_address: 'recipient@example.com', event_title: 'Team Meeting', start_time: '2024-06-10T10:00:00Z', end_time: '2024-06-10T11:00:00Z', organizer_name: 'Alice Smith', method: 'CANCEL', location: 'Conference Room 1', description: 'Meeting has been cancelled', attendees: ['recipient@example.com', 'pennie@a1base.com'], mail_headers: { sequence: 1 } }; axios.post(url, data, { headers }) .then(response => console.log(response.data)) .catch(error => console.error('Error:', error)); ``` We'd love to hear from you! Don't hesitate to reach out to [pennie@a1base.com](mailto:pennie@a1base.com) or [pasha@a1base.com](mailto:pasha@a1base.com) if there's any features you'd like to see or prioritised! ## Calendar Invite Methods The A1Mail API supports different calendar methods for managing events: ### REQUEST Used to create new calendar events or invite attendees to an event. This is the most common method for sending calendar invites. ### CANCEL Used to cancel an existing calendar event. When using this method, make sure to increment the `sequence` number in `mail_headers` to indicate this is an update to the original event. ### REPLY Used by attendees to respond to calendar invites (Accept, Decline, Tentative). This method is typically used when building calendar applications that need to handle responses. ## Time Format Guidelines All time values should be provided in ISO 8601 format with UTC timezone: * **Format**: `YYYY-MM-DDTHH:MM:SSZ` * **Example**: `2024-06-10T10:00:00Z` * **Time Zone**: Always use UTC (Z suffix) The recipient's calendar application will automatically convert times to their local timezone for display. ## Working with Attendees When specifying attendees, provide an array of email addresses. The system will automatically: * Send calendar invites to all specified attendees * Handle RSVP responses if configured * Track attendance status for each attendee ## Understanding Sequence Numbers The `mail_headers` field, specifically the `sequence` attribute, is used in calendar invites to manage updates to events. Here's how it works: ### Purpose of Sequence in Calendar Invites **Event Versioning**: The sequence number is used to track the version of a calendar event. Each time an event is updated (e.g., time change, location change), the sequence number is incremented. This helps recipients' calendar applications understand that the event has been modified and that they should update the existing event details with the new information. **Conflict Resolution**: By using a sequence number, calendar systems can resolve conflicts between different versions of the same event. If a recipient receives multiple updates for the same event, the update with the highest sequence number is considered the most recent and authoritative. **Synchronization**: It ensures that all participants have the latest version of the event. When an event organizer sends an update, the sequence number helps ensure that all attendees' calendars are synchronized with the latest event details. ### How It Works * **Initial Event**: When an event is first created, the sequence number is typically set to `0` * **Event Update**: If the event is updated, the sequence number is incremented (e.g., from `0` to `1`) * **Event Cancellation**: If the event is canceled, the sequence number is also incremented to indicate a change ### Example Sequence Flow 1. **Original Event**: `sequence: 0` 2. **First Update**: `sequence: 1` (e.g., time changed) 3. **Second Update**: `sequence: 2` (e.g., location changed) 4. **Cancellation**: `sequence: 3` By using the sequence number, calendar applications can ensure that they are displaying the most current version of an event to users. # Sending Emails Source: https://docs.a1base.com/a1mail/sending-email Send emails programmatically through the A1Mail API with just a few lines of code ## Request Parameters The following parameters are used when sending an email: | Parameter | Type | Required | Description | | ------------------- | ------ | -------- | --------------------------------------------------------------- | | `sender_address` | string | Yes | Email address that will appear in the "From" field | | `recipient_address` | string | Yes | Email address of the recipient | | `subject` | string | Yes | Subject line of the email | | `body` | string | Yes | Content of the email (plain text or HTML) | | `headers` | object | No | Optional email headers as key-value pairs (cc, bcc, etc.) | | `attachment_uri` | array | No | Array of URIs pointing to files you want to attach to the email | ## Code Examples ### Send a Simple Text Email ```bash curl --location 'https://api.a1base.com/v1/emails/{account_id}/send' \ --header 'X-API-Key: YOUR_API_KEY' \ --header 'X-API-Secret: YOUR_API_SECRET' \ --header 'Content-Type: application/json' \ --data-raw '{ "sender_address": "hello@a1send.com", "recipient_address": "recipient@example.com", "subject": "Hello from A1Base", "body": "This is an example email body.", "headers": {} }' ``` ### Send an HTML Email ````bash curl --location 'https://api.a1base.com/v1/emails/{account_id}/send' \ --header 'X-API-Key: YOUR_API_KEY' \ --header 'X-API-Secret: YOUR_API_SECRET' \ --header 'Content-Type: application/json' \ --data-raw '{ "sender_address": "hello@a1send.com", "recipient_address": "recipient@example.com", "subject": "Hello from A1Base", "body": "A1Mail for AI Agents

    Hey,

    Welcome to A1Mail!
    A1Mail is an email API made for AI agents who chat, not spam.

    With A1Mail you can:

    • Create new addresses via a simple API
    • Send emails effortlessly
    • Receive messages instantly via webhooks
    • Protect deliverability with built-in spam filters
    • Integrate with any AI system
    • Enjoy transparent pricing—no hidden fees
    • Use your own subdomain for AI agents
    Find out more at www.a1mail.com.

    ", "headers": { "cc": "pennie@a1base.com", "bcc": "pasha@a1base.com" } }' ### Send an Email with Attachments ```bash curl --location 'https://api.a1base.com/v1/emails/{account_id}/send' \ --header 'X-API-Key: YOUR_API_KEY' \ --header 'X-API-Secret: YOUR_API_SECRET' \ --header 'Content-Type: application/json' \ --data-raw '{ "sender_address": "hello@a1send.com", "recipient_address": "recipient@example.com", "subject": "Email with Attachments", "body": "Please find the attached files.", "headers": {}, "attachment_uri": [ "https://example.com/files/document.pdf", "https://example.com/files/image.jpg" ] }' ````
    ### Send a Simple Text Email ```python import requests import json url = "https://api.a1base.com/v1/emails/{account_id}/send" headers = { 'X-API-Key': 'YOUR_API_KEY', 'X-API-Secret': 'YOUR_API_SECRET', 'Content-Type': 'application/json' } data = { "sender_address": "hello@a1send.com", "recipient_address": "recipient@example.com", "subject": "Hello from A1Base", "body": "This is an example email body.", "headers": {} } response = requests.post(url, headers=headers, data=json.dumps(data)) print(response.json()) ``` ### Send an HTML Email ```python import requests import json url = "https://api.a1base.com/v1/emails/{account_id}/send" headers = { 'X-API-Key': 'YOUR_API_KEY', 'X-API-Secret': 'YOUR_API_SECRET', 'Content-Type': 'application/json' } html_body = """ A1Mail for AI Agents

    Hey,

    Welcome to A1Mail!
    A1Mail is an email API made for AI agents who chat, not spam.

    With A1Mail you can:

    • Create new addresses via a simple API
    • Send emails effortlessly
    • Receive messages instantly via webhooks
    • Protect deliverability with built-in spam filters
    • Integrate with any AI system
    • Enjoy transparent pricing—no hidden fees
    • Use your own subdomain for AI agents

    Find out more at www.a1mail.com.

    """ data = { "sender_address": "hello@a1send.com", "recipient_address": "recipient@example.com", "subject": "Hello from A1Base", "body": html_body, "headers": { "cc": "pennie@a1base.com", "bcc": "pasha@a1base.com" } } response = requests.post(url, headers=headers, data=json.dumps(data)) print(response.json()) ``` ### Send an Email with Attachments ```python import requests import json url = "https://api.a1base.com/v1/emails/{account_id}/send" headers = { 'X-API-Key': 'YOUR_API_KEY', 'X-API-Secret': 'YOUR_API_SECRET', 'Content-Type': 'application/json' } data = { "sender_address": "hello@a1send.com", "recipient_address": "recipient@example.com", "subject": "Email with Attachments", "body": "Please find the attached files.", "headers": {}, "attachment_uri": [ "https://example.com/files/document.pdf", "https://example.com/files/image.jpg" ] } response = requests.post(url, headers=headers, data=json.dumps(data)) print(response.json()) ```
    ### Send a Simple Text Email ```javascript const axios = require('axios'); const url = 'https://api.a1base.com/v1/emails/{account_id}/send'; const headers = { 'X-API-Key': 'YOUR_API_KEY', 'X-API-Secret': 'YOUR_API_SECRET', 'Content-Type': 'application/json' }; const data = { sender_address: 'hello@a1send.com', recipient_address: 'recipient@example.com', subject: 'Hello from A1Base', body: 'This is an example email body.', headers: {} }; axios.post(url, data, { headers }) .then(response => console.log(response.data)) .catch(error => console.error('Error:', error)); ``` ### Send an HTML Email ```javascript const axios = require('axios'); const url = 'https://api.a1base.com/v1/emails/{account_id}/send'; const headers = { 'X-API-Key': 'YOUR_API_KEY', 'X-API-Secret': 'YOUR_API_SECRET', 'Content-Type': 'application/json' }; const htmlBody = ` A1Mail for AI Agents

    Hey,

    Welcome to A1Mail!
    A1Mail is an email API made for AI agents who chat, not spam.

    With A1Mail you can:

    • Create new addresses via a simple API
    • Send emails effortlessly
    • Receive messages instantly via webhooks
    • Protect deliverability with built-in spam filters
    • Integrate with any AI system
    • Enjoy transparent pricing—no hidden fees
    • Use your own subdomain for AI agents

    Find out more at www.a1mail.com.

    `; const data = { sender_address: 'hello@a1send.com', recipient_address: 'recipient@example.com', subject: 'Hello from A1Base', body: htmlBody, headers: { cc: 'pennie@a1base.com', bcc: 'pasha@a1base.com' } }; axios.post(url, data, { headers }) .then(response => console.log(response.data)) .catch(error => console.error('Error:', error)); ``` ### Send an Email with Attachments ```javascript const axios = require('axios'); const url = 'https://api.a1base.com/v1/emails/{account_id}/send'; const headers = { 'X-API-Key': 'YOUR_API_KEY', 'X-API-Secret': 'YOUR_API_SECRET', 'Content-Type': 'application/json' }; const data = { sender_address: 'hello@a1send.com', recipient_address: 'recipient@example.com', subject: 'Email with Attachments', body: 'Please find the attached files.', headers: {}, attachment_uri: [ 'https://example.com/files/document.pdf', 'https://example.com/files/image.jpg' ] }; axios.post(url, data, { headers }) .then(response => console.log(response.data)) .catch(error => console.error('Error:', error)); ```
    We'd love to hear from you! Don't hesitate to reach out to [pennie@a1base.com](mailto:pennie@a1base.com) or [pasha@a1base.com](mailto:pasha@a1base.com) if there's any features you'd like to see or prioritised! ## Working with Attachments To include attachments in your emails, use the `attachment_uri` parameter which accepts an array of URLs pointing to the files you want to attach. ### Supported Attachment Types A1Mail supports most common file types for email attachments, including but not limited to: * PDF documents (\*.pdf) * Images (\*.jpg, \*.jpeg, \*.png, \*.gif) * Office documents (\*.docx, \*.xlsx, \*.pptx) * Text files (\*.txt, \*.csv) ### Attachment Size Limits Attachments are subject to size limitations. Please ensure your attachments adhere to the following guidelines: * Individual attachment: Maximum 10MB * Total attachments per email: Maximum 25MB ### Hosting Attachments Attachments must be accessible via a public URL. You can use your own hosting solution or any publicly accessible file storage service. Make sure the URLs provided in the `attachment_uri` array are directly accessible without authentication. # A1Zap Source: https://docs.a1base.com/a1zap/index Yap with friends and AI # A1Zap Let your agent message users, groups, and communities directly within the A1Zap app. List your agent on our platform and let people start conversations with it using our API. Download the A1Zap app here: [https://apps.apple.com/au/app/a1zap/id6748840042](https://apps.apple.com/au/app/a1zap/id6748840042) Download A1Zap on the iOS AppStore Now → Get started # Messaging API Source: https://docs.a1base.com/a1zap/messaging-api Send and retrieve messages with A1Zap ## Messaging API Use these endpoints to send individual messages and fetch recent messages. ### Send an Individual Message Replace placeholders like ``, ``, and `` with your values. ```bash curl -X POST "https://api.a1zap.com/v1/messages/individual//send" \ -H "Content-Type: application/json" \ -H "X-API-Key: " \ -d '{ "metadata" : { "source" : "ios" }, "chatId" : "", "content" : "Hello from the API!" }' ``` ### Get Messages (via Agent Webhook Runner) ```bash curl -X POST "https://api.a1zap.com/api/run/agentWebhook/getMessages" \ -H "Content-Type: application/json" \ -d '{ "args" : { "agentId" : "", "apiKey" : "", "chatId" : "", "limit" : 25 }, "format" : "json" }' ``` #### Notes * `X-API-Key` should be an API key with permissions to send/read messages for the target agent. * `chatId` identifies the conversation thread. * `metadata.source` is optional and can be used for analytics/debugging. # Cron Jobs API Source: https://docs.a1base.com/api-reference/cron-jobs/introduction API reference for managing scheduled tasks # Cron Jobs API The A1Base Cron Jobs API allows you to programmatically create, manage, and monitor scheduled tasks for your AI agents. ## Authentication All API requests require authentication using your A1Base API key. Include your API key in the Authorization header: ```bash Authorization: Bearer YOUR_API_KEY ``` ## Base URL ``` https://api.a1base.com/v1 ``` ## Endpoints ### Create a Cron Job ```bash POST /cron-jobs ``` Create a new scheduled task that will execute at the specified intervals. #### Request Body | Parameter | Type | Required | Description | | ----------------- | ------- | -------- | ------------------------------------------------------------ | | `endpoint_url` | string | Yes | The URL to be called when the cron job executes | | `frequency` | string | Yes | Frequency of execution (daily, weekly, monthly, custom) | | `time` | string | Yes | Time of execution in 24-hour format (HH:MM) | | `timezone` | string | Yes | Timezone for the execution time (e.g., America/Los\_Angeles) | | `method` | string | Yes | HTTP method to use (GET, POST, PUT, DELETE) | | `headers` | object | No | HTTP headers to include with the request | | `body` | object | No | Request body for POST/PUT methods | | `day_of_week` | integer | No | Day of week for weekly jobs (0-6, where 0 is Sunday) | | `day_of_month` | integer | No | Day of month for monthly jobs (1-31) | | `custom_schedule` | string | No | Cron expression for custom schedules | #### Example Request ```json { "endpoint_url": "https://api.example.com/webhook", "frequency": "daily", "time": "09:00", "timezone": "America/New_York", "method": "POST", "headers": { "Authorization": "Bearer token123", "Content-Type": "application/json" }, "body": { "action": "daily_update", "params": { "user_id": "all" } } } ``` #### Example Response ```json { "id": "crn_123456789", "endpoint_url": "https://api.example.com/webhook", "frequency": "daily", "time": "09:00", "timezone": "America/New_York", "method": "POST", "headers": { "Authorization": "Bearer token123", "Content-Type": "application/json" }, "body": { "action": "daily_update", "params": { "user_id": "all" } }, "status": "active", "created_at": "2023-05-20T15:30:45Z", "next_execution": "2023-05-21T09:00:00-04:00" } ``` ### List All Cron Jobs ```bash GET /cron-jobs ``` Retrieve a list of all cron jobs for your account. #### Query Parameters | Parameter | Type | Required | Description | | --------- | ------- | -------- | ----------------------------------------------------------- | | `status` | string | No | Filter by status (active, paused) | | `limit` | integer | No | Maximum number of records to return (default: 20, max: 100) | | `offset` | integer | No | Number of records to skip (for pagination) | #### Example Response ```json { "data": [ { "id": "crn_123456789", "endpoint_url": "https://api.example.com/webhook", "frequency": "daily", "time": "09:00", "timezone": "America/New_York", "method": "POST", "status": "active", "created_at": "2023-05-20T15:30:45Z", "next_execution": "2023-05-21T09:00:00-04:00" }, { "id": "crn_987654321", "endpoint_url": "https://api.example.com/weekly-report", "frequency": "weekly", "time": "07:00", "day_of_week": 1, "timezone": "America/Los_Angeles", "method": "GET", "status": "paused", "created_at": "2023-05-15T10:20:30Z", "next_execution": null } ], "meta": { "total": 2, "limit": 20, "offset": 0 } } ``` ### Get a Cron Job ```bash GET /cron-jobs/{id} ``` Retrieve details for a specific cron job. #### Path Parameters | Parameter | Type | Required | Description | | --------- | ------ | -------- | ---------------------- | | `id` | string | Yes | The ID of the cron job | #### Example Response ```json { "id": "crn_123456789", "endpoint_url": "https://api.example.com/webhook", "frequency": "daily", "time": "09:00", "timezone": "America/New_York", "method": "POST", "headers": { "Authorization": "Bearer token123", "Content-Type": "application/json" }, "body": { "action": "daily_update", "params": { "user_id": "all" } }, "status": "active", "created_at": "2023-05-20T15:30:45Z", "next_execution": "2023-05-21T09:00:00-04:00", "last_execution": { "timestamp": "2023-05-20T09:00:00-04:00", "status": "success", "response_code": 200, "response_time_ms": 245 } } ``` ### Update a Cron Job ```bash PATCH /cron-jobs/{id} ``` Update the configuration of an existing cron job. #### Path Parameters | Parameter | Type | Required | Description | | --------- | ------ | -------- | ---------------------- | | `id` | string | Yes | The ID of the cron job | #### Request Body Include only the fields you want to update. #### Example Request ```json { "time": "10:30", "headers": { "Authorization": "Bearer new_token456", "Content-Type": "application/json" } } ``` #### Example Response ```json { "id": "crn_123456789", "endpoint_url": "https://api.example.com/webhook", "frequency": "daily", "time": "10:30", "timezone": "America/New_York", "method": "POST", "headers": { "Authorization": "Bearer new_token456", "Content-Type": "application/json" }, "body": { "action": "daily_update", "params": { "user_id": "all" } }, "status": "active", "created_at": "2023-05-20T15:30:45Z", "updated_at": "2023-05-20T16:45:12Z", "next_execution": "2023-05-21T10:30:00-04:00" } ``` ### Pause a Cron Job ```bash POST /cron-jobs/{id}/pause ``` Temporarily pause the execution of a cron job. #### Path Parameters | Parameter | Type | Required | Description | | --------- | ------ | -------- | ---------------------- | | `id` | string | Yes | The ID of the cron job | #### Example Response ```json { "id": "crn_123456789", "status": "paused", "next_execution": null } ``` ### Resume a Cron Job ```bash POST /cron-jobs/{id}/resume ``` Resume a paused cron job. #### Path Parameters | Parameter | Type | Required | Description | | --------- | ------ | -------- | ---------------------- | | `id` | string | Yes | The ID of the cron job | #### Example Response ```json { "id": "crn_123456789", "status": "active", "next_execution": "2023-05-21T10:30:00-04:00" } ``` ### Delete a Cron Job ```bash DELETE /cron-jobs/{id} ``` Permanently delete a cron job. #### Path Parameters | Parameter | Type | Required | Description | | --------- | ------ | -------- | ---------------------- | | `id` | string | Yes | The ID of the cron job | #### Example Response ```json { "id": "crn_123456789", "deleted": true } ``` ### Get Execution History ```bash GET /cron-jobs/{id}/executions ``` Retrieve the execution history for a specific cron job. #### Path Parameters | Parameter | Type | Required | Description | | --------- | ------ | -------- | ---------------------- | | `id` | string | Yes | The ID of the cron job | #### Query Parameters | Parameter | Type | Required | Description | | --------- | ------- | -------- | ----------------------------------------------------------- | | `status` | string | No | Filter by execution status (success, failed) | | `limit` | integer | No | Maximum number of records to return (default: 20, max: 100) | | `offset` | integer | No | Number of records to skip (for pagination) | #### Example Response ```json { "data": [ { "id": "exe_987654321", "cron_job_id": "crn_123456789", "timestamp": "2023-05-20T09:00:00-04:00", "status": "success", "response_code": 200, "response_time_ms": 245, "response_body": { "status": "processed", "message": "Daily update successfully triggered" } }, { "id": "exe_876543210", "cron_job_id": "crn_123456789", "timestamp": "2023-05-19T09:00:00-04:00", "status": "failed", "response_code": 500, "response_time_ms": 1245, "error": "Internal server error at destination" } ], "meta": { "total": 2, "limit": 20, "offset": 0 } } ``` ## Error Responses | Status Code | Description | | ----------- | --------------------------------------- | | 400 | Bad Request - Invalid parameters | | 401 | Unauthorized - Authentication failed | | 403 | Forbidden - Insufficient permissions | | 404 | Not Found - Resource does not exist | | 429 | Too Many Requests - Rate limit exceeded | | 500 | Internal Server Error | ### Example Error Response ```json { "error": { "code": "validation_error", "message": "Invalid frequency value", "details": { "frequency": ["Must be one of: daily, weekly, monthly, custom"] } } } ``` # Create Messages Source: https://docs.a1base.com/api-reference/endpoint/create POST /messages/individual/{accountId}/send Send a message to an individual recipient ### Sending Messages: * **Group Chats**: The agent's phone number must first be added to the group chat before messages can be sent. * **Individual Chats**: A user must initiate the conversation with the agent's phone number before the agent can send messages. **NPM Package** [**https://www.npmjs.com/package/a1base-api**](https://www.npmjs.com/package/a1base-api) ### Sending Text Messages ```json POST /individual/{accountId}/send Headers: x-api-key: your_api_key x-api-secret: your_api_secret Content-Type: application/json Body: { "from": "+14155552671", "to": "+14155551234", "service": "whatsapp", "message": "Hello, this is a test message!" } ``` ### Sending Media Messages #### Individual Media Message To send an image to an individual: ```json POST /individual/{accountId}/send Headers: x-api-key: your_api_key x-api-secret: your_api_secret Content-Type: application/json Body: { "from": "+14155552671", "to": "+14155551234", "service": "whatsapp", "message_type": "media", "media_url": "https://example.com/images/sample.jpg", "media_type": "image", "caption": "Check out this image!" } ``` ### Using the Universal Endpoint You can also use the newer universal endpoint for both text and media messages: ```json POST /send/{accountId} Headers: x-api-key: your_api_key x-api-secret: your_api_secret Content-Type: application/json Body: { "from": "+14155552671", "to": "+14155551234", "service": "whatsapp", "type": "individual", "content": { "type": "media", "media_url": "https://example.com/videos/demo.mp4", "media_type": "video", "caption": "Product demo video" } } ``` ### Supported Media Types The API supports these media types: * **image**: For images (JPG, PNG, etc.) * **video**: For video files * **audio**: For audio files * **document**: For documents (PDF, DOC, etc.) ### Important Notes * The `media_url` must be a publicly accessible URL where the media file can be downloaded. * The `caption` field is optional. You can send media without a caption if desired. * Make sure your media files are in formats supported by WhatsApp. * There are size limits for different media types: * Images: Generally up to 5MB * Videos: Generally up to 16MB * Audio: Generally up to 16MB * Documents: Generally up to 100MB * The `from` number must be a WhatsApp-enabled number that your account has permission to use. * The `to` number for individual messages must be a valid WhatsApp number. # Get Messages Source: https://docs.a1base.com/api-reference/endpoint/get GET /messages/individual/{accountId}/get-details/{messageId} Get details for a specific message # Group Management Source: https://docs.a1base.com/api-reference/group-management/create POST /whatsapp/{accountId}/group-management The group management endpoint allows you to perform various WhatsApp group operations including creating groups, managing participants, and updating group settings. ### Key Operations: * Create new groups with specified participants * Update group details (name, description, picture) * Manage participants (add, remove, promote/demote admins) * Handle group invites and messaging permissions ### Example Request ```bash curl --location 'https://api.a1base.com/v1/whatsapp/{accountId}/group-management' \ --header 'x-api-key: YOUR_API_KEY' \ --header 'x-api-secret: YOUR_API_SECRET' \ --header 'Content-Type: application/json' \ --data '{ "action": "create", "agent_number": "+1234567890", "title": "New Group", "participants": ["+1987654321"] }' ``` ### Request Body The operation to perform. Valid values: * `create` * `update_name` * `update_description` * `update_picture` * `add_participants` * `remove_participants` * `promote_admin` * `demote_admin` * `join` * `leave` * `update_settings` The phone number initiating the action (must start with '+') The group chat ID. Required for all actions except 'create' ### Action-Specific Fields Required fields for `action: "create"`: * `title` (string): Group name * `participants` (array): Phone numbers to add * `initial_message` (string, optional): First message to send Fields for update actions: * `name` (string): New group name (`update_name`) * `description` (string): New description (`update_description`) * `image_url` (string): New profile picture URL (`update_picture`) Required for participant management actions: * `participants` (array): Phone numbers to modify For actions: `add_participants`, `remove_participants`, `promote_admin`, `demote_admin` Required for `action: "join_group"`: * `invite_code` (string): Group invite code * `thread_id` (string): Direct group ID (if already have access) Required for `update_settings`: * `setting` (string): One of: * `announcement`: Only admins can send messages in the group * `not_announcement`: All participants can send messages in the group * `locked`: Only admins can modify group settings (display picture, description, etc) * `unlocked`: All participants can modify group settings ### Example Requests ```bash curl --location 'https://api.a1base.com/v1/whatsapp/{accountId}/group-management' \ --header 'x-api-key: YOUR_API_KEY' \ --header 'x-api-secret: YOUR_API_SECRET' \ --header 'Content-Type: application/json' \ --data '{ "action": "create", "agent_number": "+1234567890", "title": "Project Team", "participants": ["+1987654321", "+1012345678"], "initial_message": "Welcome to the project team group!" }' ``` ```bash # Update Name curl --location 'https://api.a1base.com/v1/whatsapp/{accountId}/group-management' \ --header 'x-api-key: YOUR_API_KEY' \ --header 'x-api-secret: YOUR_API_SECRET' \ --header 'Content-Type: application/json' \ --data '{ "action": "update_name", "agent_number": "+1234567890", "thread_id": "123123", "name": "A1Base Project Team" }' # Update Description curl --location 'https://api.a1base.com/v1/whatsapp/{accountId}/group-management' \ --header 'x-api-key: YOUR_API_KEY' \ --header 'x-api-secret: YOUR_API_SECRET' \ --header 'Content-Type: application/json' \ --data '{ "action": "update_description", "agent_number": "+1234567890", "thread_id": "123123", "description": "Official group for project coordination" }' # Update Picture curl --location 'https://api.a1base.com/v1/whatsapp/{accountId}/group-management' \ --header 'x-api-key: YOUR_API_KEY' \ --header 'x-api-secret: YOUR_API_SECRET' \ --header 'Content-Type: application/json' \ --data '{ "action": "update_picture", "agent_number": "+1234567890", "thread_id": "123123", "image_url": "https://example.com/group-image.jpg" }' ``` ```bash # Add Participants curl --location 'https://api.a1base.com/v1/whatsapp/{accountId}/group-management' \ --header 'x-api-key: YOUR_API_KEY' \ --header 'x-api-secret: YOUR_API_SECRET' \ --header 'Content-Type: application/json' \ --data '{ "action": "add_participants", "agent_number": "+1234567890", "thread_id": "123123", "participants": ["+1555999888", "+1555777666"] }' # Remove Participants curl --location 'https://api.a1base.com/v1/whatsapp/{accountId}/group-management' \ --header 'x-api-key: YOUR_API_KEY' \ --header 'x-api-secret: YOUR_API_SECRET' \ --header 'Content-Type: application/json' \ --data '{ "action": "remove_participants", "agent_number": "+1234567890", "thread_id": "123123", "participants": ["+1555999888"] }' # Promote Admin curl --location 'https://api.a1base.com/v1/whatsapp/{accountId}/group-management' \ --header 'x-api-key: YOUR_API_KEY' \ --header 'x-api-secret: YOUR_API_SECRET' \ --header 'Content-Type: application/json' \ --data '{ "action": "promote_admin", "agent_number": "+1234567890", "thread_id": "123123", "participants": ["+1555777666"] }' # Demote Admin curl --location 'https://api.a1base.com/v1/whatsapp/{accountId}/group-management' \ --header 'x-api-key: YOUR_API_KEY' \ --header 'x-api-secret: YOUR_API_SECRET' \ --header 'Content-Type: application/json' \ --data '{ "action": "demote_admin", "agent_number": "+1234567890", "thread_id": "123123", "participants": ["+1555777666"] }' ``` ```bash # Join Group curl --location 'https://api.a1base.com/v1/whatsapp/{accountId}/group-management' \ --header 'x-api-key: YOUR_API_KEY' \ --header 'x-api-secret: YOUR_API_SECRET' \ --header 'Content-Type: application/json' \ --data '{ "action": "join_group", "agent_number": "+1234567890", "thread_id": "123123" }' # Leave Group curl --location 'https://api.a1base.com/v1/whatsapp/{accountId}/group-management' \ --header 'x-api-key: YOUR_API_KEY' \ --header 'x-api-secret: YOUR_API_SECRET' \ --header 'Content-Type: application/json' \ --data '{ "action": "leave", "agent_number": "+1234567890", "thread_id": "123123" }' # Update Group Settings curl --location 'https://api.a1base.com/v1/whatsapp/{accountId}/group-management' \ --header 'x-api-key: YOUR_API_KEY' \ --header 'x-api-secret: YOUR_API_SECRET' \ --header 'Content-Type: application/json' \ --data '{ "action": "update_settings", "agent_number": "+1234567890", "thread_id": "123123", "setting": "announcement" }' ``` # Create Group Messages Source: https://docs.a1base.com/api-reference/group-messages/create POST /messages/group/{accountId}/send Send a message to a group chat ### Sending Group Messages: * The agent's phone number must first be added to the group chat before messages can be sent. * You'll need the thread\_id of the group chat to send messages. This is provided when you create a group or in webhook events. ### Example Request #### Text Message to Group ```json POST /group/{accountId}/send Headers: x-api-key: your_api_key x-api-secret: your_api_secret Content-Type: application/json Body: { "from": "+14155552671", "thread_id": "group-thread-id-123", "service": "whatsapp", "message": "Hello everyone in the group!" } ``` #### Media Message to Group To send a document to a group: ```json POST /group/{accountId}/send Headers: x-api-key: your_api_key x-api-secret: your_api_secret Content-Type: application/json Body: { "from": "+14155552671", "thread_id": "group-thread-id-123", "service": "whatsapp", "message_type": "media", "media_url": "https://example.com/documents/report.pdf", "media_type": "document", "caption": "Here's the quarterly report" } ``` ### Using the Universal Endpoint for Groups You can also use the newer universal endpoint for group messages: ```json POST /send/{accountId} Headers: x-api-key: your_api_key x-api-secret: your_api_secret Content-Type: application/json Body: { "from": "+14155552671", "thread_id": "group-thread-id-123", "service": "whatsapp", "type": "group", "content": { "type": "media", "media_url": "https://example.com/videos/demo.mp4", "media_type": "video", "caption": "Product demo video for the team" } } ``` ### Important Notes for Group Media Messages * For group messages, you need a valid `thread_id` instead of a `to` number. * The `caption` field is optional. You can send media without a caption if desired. * The same media type and size restrictions apply as with individual messages: * Images: Generally up to 5MB * Videos: Generally up to 16MB * Audio: Generally up to 16MB * Documents: Generally up to 100MB * The agent must be a member of the group before sending messages. # Introduction Source: https://docs.a1base.com/api-reference/introduction Using the A1Base API to send, receive, and manage messages on WhatsApp As we're in Alpha right now, you can only get your API key by contacting the founders at [pasha@a1base.com](mailto:pasha@a1base.com) or [pennie@a1base.com](mailto:pennie@a1base.com) ## Welcome The A1Base API allows you to give your AI Agent a phone number and send messages on WhatsApp and Telegram. ## Authentication All requests to the A1Base API must include two headers: * `X-API-Key`: Your API key * `X-API-Secret`: Your API secret If you are using our official SDKs, you will set these credentials when constructing a client, and the SDK will automatically include them with every request. If you're integrating directly with the API, you'll need to include these headers yourself. As A1Base is in Alpha your keys will be provided to you by the team after an onboarding call. # Get all threads Source: https://docs.a1base.com/api-reference/threads/get-all GET /messages/threads/{accountId}/get-all Get all threads for an account # Get by phone number Source: https://docs.a1base.com/api-reference/threads/get-by-phone GET /messages/threads/{accountId}/get-all/{phone_number} Get all threads for an account filtered by phone number # Get thread details Source: https://docs.a1base.com/api-reference/threads/get-details GET /messages/threads/{accountId}/get-details/{threadId} Get details for a specific thread # Get recent messages Source: https://docs.a1base.com/api-reference/threads/get-recent GET /messages/threads/{accountId}/get-recent/{threadId} Get the 5 most recent messages from a thread # Webhook Source: https://docs.a1base.com/api-reference/webhook/webhook POST /whatsapp/incoming Webhook endpoint for receiving incoming WhatsApp messages from WhatsApp servers The webhook endpoint allows you to receive incoming WhatsApp messages in real-time. When a message is received, it will be sent to your configured webhook URL with the following payload structure. Think of it as setting up an automatic forwarding system - whenever someone messages your AI agent on WhatsApp, we'll immediately forward that message to your specified webhook URL, so your agent can process and respond to it right away. ```json { "thread_id": "chat_123456789", "message_id": "msg_987654321", "thread_type": "individual", "sender_number": "+61400123456", "sender_name": "Jane", "a1_account_id": "123-123-123", "a1_phone_number": "+1415123456", "timestamp": "2024-12-20T00:48:15+00:00", "service": "whatsapp", "message_type": "text", "is_from_agent": false, "message_content": { "text": "Hello world" } } ``` This webhook will receive all incoming messages, including those created using the A1Base API. To prevent infinite loops, you may want to check the sender\_number to avoid agents replying to themselves. ### Webhook Payload Unique identifier for the chat thread Unique identifier for the specific message Type of chat - can be "group", "individual", or "broadcast" Phone number of the message sender with country code. e.g. "+61400123456" Name of the message sender Your A1Base account identifier Your A1Base account identifier The A1Base phone number that received the message. e.g. "+61400999888" When the message was handled on WhatsApp, in ISO 8601 format. e.g. "2024-12-20T00:48:15+00:00" The messaging service used (e.g. "whatsapp") Type of the message. Can be one of: "text", "rich\_text", "image", "video", "audio", "reaction", "group\_invite", "location", "unsupported\_message\_type" Whether the message was sent by an agent The complete message content object containing all message data. Structure varies by message\_type: For message\_type: "text" (simple text) ```json { "text": "Hello world" } ``` For message\_type: "rich\_text" (rich text with optional quote) ```json { "text": "This is a reply to something", "quoted_message_content": "Original message that was replied to", "quoted_message_sender": "61400123456" } ``` For message\_type: "image" ```json { "data": "base64_encoded_image_data" } ``` For message\_type: "video" ```json { "data": "base64_encoded_video_data" } ``` For message\_type: "audio" ```json { "data": "base64_encoded_audio_data" } ``` For message\_type: "reaction" ```json { "reaction": "👍" } ``` For message\_type: "group\_invite" ```json { "groupName": "My WhatsApp Group", "inviteCode": "Ab12Cd34" } ``` For message\_type: "location" ```json { "latitude": -33.8688, "longitude": 151.2093, "name": "Optional location name", "address": "Optional address" } ``` For message\_type: "unsupported\_message\_type" ```json { "error": "Unsupported Message Type" } ``` HMAC-SHA256 signature used to verify the authenticity of the webhook. Created using your API secret and the timestamp + request body. Unix timestamp (in seconds) when the webhook was sent. Used to verify the request and prevent replay attacks. ### Response Codes * `200`: Message received successfully * `403`: Invalid secret key * `500`: Internal server error 1. Create an endpoint in your application to receive webhook events: ```typescript import express from 'express'; import { WhatsAppIncomingData } from 'a1base-node'; const app = express(); app.use(express.json()); app.post('/whatsapp/incoming', async (req, res) => { const { thread_id, message_id, thread_type, sender_number, sender_name, a1_account_id, a1_phone_number, timestamp, service, message_type, is_from_agent, message_content, } = req.body as WhatsAppIncomingData; // Process the incoming message console.log(`Received message from ${sender_name}: ${message_content.text}`); // Always respond with 200 to acknowledge receipt res.json({ success: true }); }); ``` 2. Deploy your endpoint to a public URL (e.g. using ngrok for testing) 3. Update your webhook URL on the A1Base dashboard at [https://www.a1base.com/dashboard/phone-numbers](https://www.a1base.com/dashboard/phone-numbers) For a complete implementation example including message handling and AI responses, see our chat agent example: ```typescript:examples/chat-agent.mdx startLine: 130 endLine: 209 ``` * Validate the webhook payload structure matches the expected format * Check the sender\_number to avoid infinite loops with your own agent * Use HTTPS endpoints only * Keep your webhook URL private * Implement rate limiting if needed * Add error handling for failed message processing * All webhook requests from A1Base include an `x-signature` and `x-timestamp` header. * You can verify the authenticity of each request using your API secret and the HMAC-SHA256 algorithm. * Here's how the signature is generated on our side: ```ts const message = timestamp + JSON.stringify(body); const signature = crypto .createHmac('sha256', apiSecret) .update(message) .digest('hex'); ``` On your server, do the following to verify the signature: 1. Read the raw JSON body of the request 2. Get the x-timestamp header 3. Recreate the message string as timestamp + rawBody 4. Generate your own HMAC signature with your API secret 5. Compare it with the x-signature using a constant-time comparison **Example in Express (Node.js)** ```ts import crypto from 'crypto'; import express from 'express'; const app = express(); app.use(express.json({ verify: (req, res, buf) => { req.rawBody = buf; // capture raw body for HMAC check } })); app.post('/whatsapp/incoming', (req, res) => { const rawBody = req.rawBody.toString(); const timestamp = req.headers['x-timestamp']; const receivedSig = req.headers['x-signature']; const secret = process.env.A1BASE_API_SECRET; const expectedSig = crypto .createHmac('sha256', secret) .update(timestamp + rawBody) .digest('hex'); if (receivedSig !== expectedSig) { return res.status(403).send('Invalid signature'); } // Continue processing the verified request res.sendStatus(200); }); ``` Reject any webhook requests with a timestamp older than 5 minutes to prevent replay attacks. # Cron Jobs Source: https://docs.a1base.com/cron-jobs Configure automated tasks that run on a schedule ## Overview A1Base's Cron Jobs feature allows you to set up automated tasks that run on a defined schedule. This is particularly useful for: * Daily check-ins with your users * Scheduled data updates * Periodic notifications * Automated reporting * Triggering AI agent workflows at specific times Cron jobs make HTTP requests to your specified endpoints, allowing you to integrate with any system that accepts webhook calls. ## Creating a Cron Job To get started with cron jobs, visit: **[https://www.a1base.com/dashboard/cron-jobs](https://www.a1base.com/dashboard/cron-jobs)** 1. Navigate to the Cron Jobs section at [https://www.a1base.com/dashboard/cron-jobs](https://www.a1base.com/dashboard/cron-jobs) in your A1Base dashboard. 2. Click on "Create New Cron Job" to open the creation form. 3. Fill out the fields on the "Create Cron Job" page: * **Endpoint URL**: Enter the publicly accessible URL that will receive the HTTP request (e.g., [https://api.example.com/webhook](https://api.example.com/webhook)). * **Frequency**: Choose how often your cron job should run (e.g., Daily, Weekly, Monthly, or Custom). * **Time**: Select the specific time of day when your cron job should run. * **Timezone**: Choose your preferred timezone so the job runs at the correct local time. * **HTTP Method**: Select the HTTP method (GET, POST, PUT, DELETE, etc.). * **Headers (JSON)**: If needed, enter request headers as a JSON object (for example: `{"Authorization": "Bearer token", "Content-Type": "application/json"}`). * **Request Body** (optional): For POST or PUT requests, you can include request body data that will be sent to your endpoint. 4. When you're ready, click on "Create Cron Job" to save your new job. The URL that will receive the HTTP request when the cron job runs How often the job should run (daily, weekly, etc.) and at what time Select your preferred timezone for accurate scheduling Choose GET, POST, PUT, or other HTTP methods for your request ## Configuration Options ### Endpoint URL Provide the full URL where the cron job should send requests. Make sure it's publicly accessible so it can process incoming requests from A1Base. ### Frequency Choose when your cron job should run: * **Daily**: Runs once every day at the specified time * **Weekly**: Runs once a week on the specified day and time * **Monthly**: Runs once a month on a specified date and time * **Custom**: Define a custom schedule using standard cron syntax (advanced) ### Time & Timezone Select the time of day to run the job and the timezone to ensure it aligns with your local or desired region's clock. ### HTTP Method Select the appropriate HTTP method: * **GET**: Retrieve data from your endpoint * **POST**: Send data to create a resource * **PUT**: Send data to update a resource * **DELETE**: Remove a resource from the server ### Headers Enter your headers as a JSON object under the "Headers (JSON)" field in the form. For example: ## Example Cron Job Configurations Here are some practical examples of how to configure cron jobs for different AI agent applications: ### Example 1: Daily Customer Check-in Bot **Use Case**: Send a morning check-in message to all users asking about their day. **Configuration**: * **Endpoint URL**: `https://your-api.example.com/send-daily-checkin` * **Frequency**: Daily * **Time**: 09:00 AM * **Timezone**: America/New\_York * **HTTP Method**: POST * **Headers**: ```json { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" } ``` * **Request Body**: ```json { "message": "Good morning! How are you feeling today?", "include_name": true } ``` This cron job will automatically trigger your customer engagement system to send personalized check-in messages to all active users every morning at 9 AM Eastern Time. ### Example 2: Weekly Analytics Report **Use Case**: Generate and send a weekly performance report to business stakeholders **Configuration**: * **Endpoint URL**: `https://your-api.example.com/generate-weekly-report` * **Frequency**: Weekly * **Day**: Monday * **Time**: 06:00 AM * **Timezone**: America/Los\_Angeles * **HTTP Method**: POST * **Headers**: ```json { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" } ``` * **Request Body**: ```json { "report_type": "weekly_summary", "metrics": ["user_engagement", "conversion_rate", "response_time"], "format": "pdf", "recipients": ["team@example.com", "executives@example.com"] } ``` This cron job runs every Monday morning at 6 AM Pacific Time, generating comprehensive analytics reports and automatically distributing them to relevant team members before the work week begins. ### Example 3: Monthly Subscription Renewal Reminder **Use Case**: Send reminders to users whose subscriptions are about to expire **Configuration**: * **Endpoint URL**: `https://your-api.example.com/subscription-reminders` * **Frequency**: Monthly * **Day**: 25 * **Time**: 10:00 AM * **Timezone**: UTC * **HTTP Method**: POST * **Headers**: ```json { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" } ``` * **Request Body**: ```json { "template_id": "subscription_reminder", "days_until_expiration": 7, "include_renewal_link": true, "offer_discount": true, "discount_code": "RENEW20" } ``` This cron job executes on the 25th of each month, identifying users whose subscriptions will expire in the next week and sending them personalized renewal reminders with special incentives to encourage continued service. # Overview Source: https://docs.a1base.com/introduction ## Get Started A1Base enhances AI agents with real-world capabilities like phone numbers, email, and messaging, enabling autonomous interactions beyond chat interfaces. Through our API, AI agents can join messaging platforms, handle communications, and operate independently while maintaining full control of your system. Integrate A1Base in minutes See what you can build As we're in Alpha right now, you can only get your API key by booking an onboarding call at [https://cal.com/team/a1base/a1base-book-a-demo](https://cal.com/team/a1base/a1base-book-a-demo) or by contacting the founders at [pasha@a1base.com](mailto:pasha@a1base.com) or [pennie@a1base.com](mailto:pennie@a1base.com) ## Key Features A1Base empowers your AI agents with real-world capabilities: Join and interact in WhatsApp, Discord, Telegram groups and chats {" "} Send and receive emails autonomously {" "} Get dedicated phone numbers for your agents Enable agents to work together and share chat history ## Why A1Base? Maintain complete control of your system {" "} Send quality, spam-free messages {" "} Works across major messaging platforms Simple API to get started quickly # Introduction Source: https://docs.a1base.com/node-js/introduction Using the A1Base API to send, receive, and manage messages As we're in Alpha right now, you can only get your API key by contacting the founders at [pasha@a1base.com](mailto:pasha@a1base.com) or [pennie@a1base.com](mailto:pennie@a1base.com) ## Welcome A1Base provides a Node.js SDK to easily integrate messaging capabilities into your application. Get started by installing the package: `npm install a1base-node` Documentation for using the Node.js SDK is available [here](https://www.npmjs.com/package/a1base-node). # Quickstart Source: https://docs.a1base.com/quickstart Learn how to start using the A1Base API As we're in Alpha right now, you can only get your API key by booking an onboarding call at [https://cal.com/team/a1base/a1base-book-a-demo](https://cal.com/team/a1base/a1base-book-a-demo) or by contacting the founders at [pasha@a1base.com](mailto:pasha@a1base.com) or [pennie@a1base.com](mailto:pennie@a1base.com) ## Getting Started ### 1. Install the A1Base CLI or webhook To start using A1Base you need an API key and secret. You can get these by booking an onboarding call at [https://cal.com/team/a1base/a1base-book-a-demo](https://cal.com/team/a1base/a1base-book-a-demo) or contacting the founders at [pasha@a1base.com](mailto:pasha@a1base.com) or [pennie@a1base.com](mailto:pennie@a1base.com). ```javascript const API_KEY = YOUR_API_KEY; const API_SECRET = YOUR_API_SECRET; const ACCOUNT_ID = YOUR_ACCOUNT_ID; const FROM_NUMBER = YOUR_FROM_NUMBER; //e.g. +12345678900 ``` ### 2. Send your first message ```bash curl --location 'https://api.a1base.com/v1/messages/individual/{accountId}/send' \ --header 'Content-Type: application/json' \ --header 'X-API-Key: ' \ --header 'X-API-Secret: ' --data '{ "content": "Hello World!", "attachment_uri": "", "from": "+1222333444", "to": "+1555666777", "service": "whatsapp" }' ``` Now it's time to build your AI Agent logic around it! We just send the message and store it safely in our database, but you can build your logic around it. # Spam & Quality Checks Source: https://docs.a1base.com/spam-and-quality-checks How A1Base ensures message quality and compliance ## Message Quality Assurance At A1Base, we take message quality and compliance seriously. Every message sent through our platform undergoes rigorous automated checks before delivery to ensure it meets our standards and protects both senders and recipients. ### Pre-Send Verification Messages are analyzed using advanced algorithms to detect: * Suspicious patterns and repetitive content * Known spam triggers and phrases * Unusual sending patterns or frequencies * Mass messaging attempts We verify that messages adhere to: * Platform-specific messaging policies * Regional communication regulations * Data protection requirements * Opt-out and consent rules Each message is evaluated for: * Proper formatting and structure * Language quality and clarity * Appropriate content and tone * Media file integrity (for attachments) ## Protection Measures Intelligent rate limiting prevents message flooding and ensures natural communication patterns Automated content screening blocks inappropriate or harmful material Behavioral analysis identifies and prevents abuse patterns Continuous account activity monitoring for suspicious behavior If your message fails our quality checks, you'll receive immediate feedback explaining why and how to adjust your content to meet our standards. ## Best Practices To ensure your messages pass our quality checks: * Maintain natural conversation flows * Avoid excessive repetition * Include clear opt-out mechanisms * Respect recipient privacy * Follow platform-specific guidelines * Keep message frequency reasonable * Use appropriate language and tone # Troubleshooting Source: https://docs.a1base.com/troubleshooting Solutions to common issues with A1Base This section provides solutions to common issues you might encounter when using A1Base. Select a specific area below to find targeted troubleshooting guidance. ## Common Issues Troubleshoot webhook delivery, timeouts, and configuration problems Coming soon: Solutions for API connectivity problems ## Getting Additional Help If you can't find a solution to your problem in our troubleshooting guides, please reach out to our support team at [pennie@a1base.com](mailto:pennie@a1base.com). # Local Testing with Ngrok Source: https://docs.a1base.com/troubleshooting/local-testing-with-ngrok How to use Ngrok to test A1Base webhooks in your local development environment # Testing Webhooks Locally with Ngrok When developing applications that use A1Base webhooks, you'll need a way to receive webhook events on your local development machine. This guide explains how to use Ngrok to create a secure tunnel to your local server. ## What is Ngrok? Ngrok is a tool that creates secure tunnels from public URLs to your local machine, allowing external services like A1Base to send webhooks to your local development environment. ## Setting Up Ngrok ### Step 1: Install Ngrok 1. Visit [ngrok.com](https://ngrok.com/) and sign up for a free account 2. Download and install Ngrok for your operating system 3. Authenticate your Ngrok installation with your auth token: ```bash ngrok config add-authtoken YOUR_AUTH_TOKEN ``` ### Step 2: Start Your Local Server First, make sure your local webhook server is running. For A1Framework or NextJS you'll run "npm run dev". When you do this you'll find out what port your app is running on (e.g. localhost:3000). ### Step 3: Connect Ngrok to Your Local Port Once your local server is running, use Ngrok to create a tunnel to your local port: ```bash ngrok http 3000 ``` This will start Ngrok and display output similar to: ``` Session Status online Account Your Name (Plan: Free) Version 3.3.1 Region United States (us) Latency 24ms Web Interface http://127.0.0.1:4040 Forwarding https://a1b2-203-0-113-42.ngrok-free.app -> http://localhost:3000 ``` The `https://a1b2-203-0-113-42.ngrok-free.app` URL is your public webhook URL that you'll configure in the A1Base dashboard. Ngrok free tier URLs change every time you restart Ngrok. You get one free consistent URL with Ngrok. For consistent URLs, consider upgrading to a paid plan. ## Configuring A1Base with Your Ngrok URL To configure your Ngrok URL in the A1Base dashboard, follow these steps: 1. Log in to the A1Base dashboard at [https://www.a1base.com/dashboard/phone-numbers](https://www.a1base.com/dashboard/phone-numbers). 2. Navigate to the "Phone Numbers" section and locate the phone number you wish to configure (e.g., 14155356190). 3. In the "Webhook URL" column for that phone number, enter your Ngrok HTTPS URL combined with your endpoint path (e.g., [https://a1b2-203-0-113-42.ngrok-free.app/whatsapp/incoming](https://a1b2-203-0-113-42.ngrok-free.app/whatsapp/incoming)). 4. Click the "Save" button next to the webhook URL field to apply the changes. Refer to the A1Base dashboard screenshot for a visual guide on configuring webhook URLs: [Phone Numbers Dashboard](link-to-screenshot). ## Development vs. Production Phone Numbers For a smooth development workflow, we recommend purchasing two separate phone numbers on A1Base: one for development and one for production. ### Why Use Separate Phone Numbers? Using separate phone numbers for development and production environments offers several advantages: 1. **Isolated Testing**: Test new features without affecting your production users 2. **Prevent Webhook Conflicts**: Avoid routing production messages to your development environment 3. **Easier Debugging**: Clearly distinguish between development and production traffic 4. **Safer Experimentation**: Experiment with new features risk-free ### Setting Up Development and Production Numbers 1. **Purchase Two Phone Numbers**: In your A1Base dashboard, purchase two separate phone numbers 2. **Label Your Numbers**: Clearly label one as "Development" and one as "Production" 3. **Configure Different Webhooks**: * Development number: Point to your Ngrok URL * Production number: Point to your production server URL 4. **Use Environment Variables**: In your code, use environment variables to determine which phone number to use: ```javascript // Example of using different phone numbers based on environment const phoneNumber = process.env.NODE_ENV === 'production' ? process.env.A1BASE_PRODUCTION_PHONE : process.env.A1BASE_DEVELOPMENT_PHONE; // Use the appropriate phone number for outgoing messages a1base.sendMessage({ to: recipientNumber, from: phoneNumber, message: "Hello from A1Base!" }); ``` ## Monitoring Webhook Traffic Ngrok provides a web interface at `http://127.0.0.1:4040` where you can inspect: * All incoming webhook requests * Request and response headers * Request and response bodies * Timing information This interface is invaluable for debugging webhook issues during development. ## Best Practices for Local Testing 1. **Keep Ngrok Running**: Maintain your Ngrok session while testing to avoid URL changes 2. **Log All Webhook Data**: Implement comprehensive logging in your development environment 3. **Simulate Different Scenarios**: Test various message types and edge cases 4. **Verify Webhook Signatures**: Even in development, validate webhook signatures if available 5. **Test Error Handling**: Ensure your application handles webhook failures gracefully ## Limitations and Considerations * **Free Tier Restrictions**: Ngrok's free tier has limitations on connections and features * **URL Changes**: Free Ngrok URLs change each time you restart Ngrok * **Latency**: There may be slight additional latency when using Ngrok * **Security**: Be cautious about sensitive data passing through your development environment By following this guide, you can effectively test A1Base webhooks in your local development environment using Ngrok, ensuring a smooth transition to production. # Webhook Issues Source: https://docs.a1base.com/troubleshooting/webhook-issues Troubleshooting common webhook problems and how to resolve them ## Common Webhook Problems ### Webhook Not Receiving Messages If your webhook isn't receiving expected messages, check the following: 1. **Verify the webhook URL** in your A1Base dashboard is correct and publicly accessible. 2. **Use the right URL route** - sometimes people forget to add the specific route of the website (e.g. /apu/receive-message) 3. **Check your server logs** for any incoming requests that might be failing 4. **Ensure your server is accepting POST requests** with JSON content 5. **Confirm your firewall settings** allow incoming webhook requests 6. **Verify SSL/TLS certificates** if you're using HTTPS (required for production) **Quick Test:** ```bash # Test if your endpoint is publicly accessible curl -X POST https://your-webhook-url.com/path \ -H "Content-Type: application/json" \ -d '{"test":"payload"}' ``` ### Vercel Timeout Issues Vercel has a default function timeout of 10 seconds for hobby plans and 60 seconds for pro plans. If your webhook processing takes longer, you might experience timeouts. **Solutions:** 1. **Acknowledge webhooks immediately** and process them asynchronously: ```typescript app.post('/whatsapp/incoming', async (req, res) => { // Immediately acknowledge receipt to prevent timeout res.status(200).json({ success: true }); // Then process the webhook asynchronously try { await processWebhookAsync(req.body); } catch (error) { console.error('Error processing webhook:', error); } }); async function processWebhookAsync(data) { // Your time-consuming processing logic here } ``` 2. **Upgrade to Vercel Pro** for longer function execution times 3. **Use a serverless queue** like AWS SQS or a background job processor 4. **Consider moving webhook processing** to a different hosting provider without strict timeout limits ### Using the Right Endpoint Using incorrect webhook endpoints is a common issue that can prevent proper message delivery. **Best Practices:** 1. **Use dedicated endpoints** for different services (e.g., `/webhooks/a1base` instead of a generic `/webhook`) 2. **Include version information** in your webhook paths (e.g., `/api/v1/webhooks/a1base`) 3. **Verify the correct endpoint format** in the A1Base dashboard: * Must be a complete URL including `https://` * Must point to a publicly accessible server * Should not include query parameters unless necessary **Example of proper endpoint structure:** ``` https://your-domain.com/api/webhooks/a1base ``` **Not:** ``` your-domain.com/webhooks /api/webhooks ``` ### Authentication and Security Issues Securing your webhook is essential to prevent unauthorized access. **Security Best Practices:** 1. **Validate webhook signatures** if provided by A1Base 2. **Implement IP whitelisting** if A1Base provides a static IP range 3. **Use a webhook secret** to validate authentic requests: ```typescript import crypto from 'crypto'; app.post('/whatsapp/incoming', (req, res) => { const signature = req.headers['x-webhook-signature']; const payload = JSON.stringify(req.body); const secret = process.env.WEBHOOK_SECRET; const expectedSignature = crypto .createHmac('sha256', secret) .update(payload) .digest('hex'); if (signature !== expectedSignature) { return res.status(403).send('Invalid signature'); } // Process valid webhook res.status(200).send('Success'); }); ``` 4. **Don't expose sensitive information** in your webhook response ### Network and Infrastructure Problems Network issues can cause intermittent webhook failures. **Troubleshooting Steps:** 1. **Check your server's connectivity** and ensure it has stable internet access 2. **Monitor server load** as high CPU or memory usage can cause webhook processing delays 3. **Implement retry logic** in your webhook handler: ```typescript async function processWebhookWithRetry(data, maxRetries = 3) { let retries = 0; while (retries < maxRetries) { try { await processWebhook(data); return; // Success } catch (error) { retries++; console.error(`Attempt ${retries} failed:`, error); if (retries >= maxRetries) { console.error('Max retries reached. Giving up.'); // Consider logging to a monitoring service or error tracker break; } // Exponential backoff await new Promise(r => setTimeout(r, 1000 * Math.pow(2, retries))); } } } ``` 4. **Use a monitoring service** like Sentry, New Relic, or Datadog to track webhook reliability ### Debugging Webhook Payloads When webhooks arrive but processing fails, payload issues might be the cause. **Debugging Techniques:** 1. **Log the complete webhook payload** during development: ```typescript app.post('/whatsapp/incoming', (req, res) => { console.log('Webhook received:', JSON.stringify(req.body, null, 2)); // Implement validation to ensure all required fields are present const { thread_id, message_id, message_content } = req.body; if (!thread_id || !message_id || !message_content) { console.error('Missing required fields in webhook payload'); return res.status(400).send('Invalid payload'); } // Process valid webhook res.status(200).send('Success'); }); ``` 2. **Implement schema validation** using libraries like Joi or Zod 3. **Create a webhook simulator** for testing your handler with various payload types 4. **Set up alerting** for malformed payloads to catch API changes early ## Advanced Troubleshooting For persistent webhook issues, consider implementing these advanced solutions: 1. **Webhook queue system** to handle high volumes of incoming webhooks 2. **Dead letter queue** for failed webhook processing attempts 3. **Circuit breaker pattern** to prevent cascading failures when dependent services are down 4. **Comprehensive logging and monitoring** to track webhook reliability over time If you continue experiencing webhook issues after trying these solutions, please contact our support team at [pennie@a1base.com](mailto:pennie@a1base.com) with details about your specific problem.