Scheduling Requests

CallMeLater allows you to schedule any HTTP request to be executed at a specific time in the future. This guide covers everything you need to know about creating, managing, and optimizing your scheduled requests.

Basic Scheduling

Simple Example

Here’s how to schedule a basic HTTP request:
const scheduleData = {
  targetUrl: "https://api.example.com/webhook",
  targetMethod: "POST",
  targetHeaders: {
    "Content-Type": "application/json",
    Authorization: "Bearer your-token",
  },
  targetBody: {
    userId: "12345",
    action: "reminder",
    message: "Don't forget your appointment tomorrow!",
  },
  triggerAt: "2024-03-20T15:00:00Z",
};

const response = await fetch("https://api.callmelater.xyz/schedule", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "x-api-key": "your_api_key_here",
  },
  body: JSON.stringify(scheduleData),
});

const result = await response.json();
console.log("Scheduled:", result.scheduleId);

Request Parameters

ParameterTypeRequiredDescription
targetUrlstringThe URL to send the request to
targetMethodstringHTTP method (GET, POST, PUT, DELETE, PATCH, HEAD)
targetHeadersobjectHTTP headers to include in the request
targetBodyobjectRequest body (for POST, PUT, PATCH)
triggerAtstringISO 8601 timestamp when to execute the request

Supported HTTP Methods

CallMeLater supports all standard HTTP methods:
{
  "targetUrl": "https://api.example.com/status",
  "targetMethod": "GET",
  "targetHeaders": {
    "Authorization": "Bearer token"
  },
  "triggerAt": "2024-03-20T15:00:00Z"
}

Time Formatting

The triggerAt field must be a valid ISO 8601 timestamp in UTC.

Correct Formats

// Specific date and time
"2024-03-20T15:30:00Z";

// With milliseconds
"2024-03-20T15:30:00.123Z";

// Using Date object in JavaScript
new Date(Date.now() + 3600000).toISOString(); // 1 hour from now

Common Scheduling Patterns

// 1 hour from now
const oneHourLater = new Date(Date.now() + 60 * 60 * 1000).toISOString();

// Tomorrow at 9 AM
const tomorrow9AM = new Date();
tomorrow9AM.setDate(tomorrow9AM.getDate() + 1);
tomorrow9AM.setHours(9, 0, 0, 0);

// End of business day
const endOfDay = new Date();
endOfDay.setHours(17, 0, 0, 0);

// Next Monday at 10 AM
const nextMonday = new Date();
const daysUntilMonday = (1 + 7 - nextMonday.getDay()) % 7;
nextMonday.setDate(nextMonday.getDate() + daysUntilMonday);
nextMonday.setHours(10, 0, 0, 0);

Advanced Use Cases

Webhook Chains

Schedule multiple related requests:
const scheduleRequest = async (requestData) => {
  const response = await fetch("https://api.callmelater.xyz/schedule", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "x-api-key": "your_api_key_here",
    },
    body: JSON.stringify(requestData),
  });
  return response.json();
};

// Initial webhook
const step1 = await scheduleRequest({
  targetUrl: "https://api.example.com/process/start",
  targetMethod: "POST",
  targetBody: { processId: "proc_123" },
  triggerAt: new Date(Date.now() + 5000).toISOString(), // 5 seconds
});

// Follow-up check
const step2 = await scheduleRequest({
  targetUrl: "https://api.example.com/process/check",
  targetMethod: "GET",
  targetHeaders: { "X-Process-ID": "proc_123" },
  triggerAt: new Date(Date.now() + 300000).toISOString(), // 5 minutes
});

Conditional Scheduling

Schedule requests based on business logic:
const scheduleReminder = async (userEvent) => {
  const reminderTime = new Date(userEvent.scheduledDate);
  reminderTime.setHours(reminderTime.getHours() - 24); // 24 hours before

  return await scheduleRequest({
    targetUrl: "https://api.example.com/send-reminder",
    targetMethod: "POST",
    targetBody: {
      userId: userEvent.userId,
      eventType: userEvent.type,
      reminderText: `Don't forget about your ${userEvent.type} tomorrow!`,
    },
    triggerAt: reminderTime.toISOString(),
  });
};

Batch Scheduling

Schedule multiple requests efficiently:
const batchSchedule = async (requests) => {
  const results = await Promise.allSettled(
    requests.map((request) => scheduleRequest(request))
  );

  const successful = results.filter((r) => r.status === "fulfilled").length;
  const failed = results.filter((r) => r.status === "rejected").length;

  console.log(`Scheduled: ${successful}, Failed: ${failed}`);
  return results;
};

// Usage
await batchSchedule([
  {
    targetUrl: "https://api.example.com/user/1/reminder",
    targetMethod: "POST",
    triggerAt: "2024-03-20T09:00:00Z",
  },
  {
    targetUrl: "https://api.example.com/user/2/reminder",
    targetMethod: "POST",
    triggerAt: "2024-03-20T09:00:00Z",
  },
]);

Managing Scheduled Requests

Canceling Requests

Cancel a scheduled request before it executes:
const cancelSchedule = async (scheduleId) => {
  const response = await fetch("https://api.callmelater.xyz/schedule/cancel", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "x-api-key": "your_api_key_here",
    },
    body: JSON.stringify({ scheduleId }),
  });

  return response.json();
};

// Usage
await cancelSchedule("sch_abc123");

Tracking Execution

Monitor your scheduled requests:
const getScheduleLogs = async () => {
  const response = await fetch("https://api.callmelater.xyz/stats/logs", {
    headers: {
      "x-api-key": "your_api_key_here",
    },
  });

  const { logs } = await response.json();

  logs.forEach((log) => {
    console.log(`${log.scheduleId}: ${log.status} - ${log.targetUrl}`);
  });
};

Best Practices

Validate URLs

Always validate target URLs before scheduling to avoid failures

Handle Timezones

Use UTC timestamps and convert from user timezones properly

Set Reasonable Delays

Don’t schedule requests too far in the future (consider token expiry)

Monitor Execution

Regularly check logs to ensure requests are executing as expected

Error Prevention

const scheduleWithValidation = async (requestData) => {
  // Validate URL format
  try {
    new URL(requestData.targetUrl);
  } catch (error) {
    throw new Error("Invalid target URL");
  }

  // Validate trigger time is in the future
  const triggerTime = new Date(requestData.triggerAt);
  if (triggerTime <= new Date()) {
    throw new Error("Trigger time must be in the future");
  }

  // Validate method
  const validMethods = ["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD"];
  if (!validMethods.includes(requestData.targetMethod)) {
    throw new Error("Invalid HTTP method");
  }

  return scheduleRequest(requestData);
};

Limitations

  • Maximum Future Time: Requests can be scheduled up to 1 year in the future
  • Minimum Delay: Requests must be scheduled at least 30 seconds in the future
  • Timeout: Target requests timeout after 30 seconds
  • Retries: Failed requests are not automatically retried
  • Size Limits: Request body size limited to 1MB