JavaScript SDK
The CallMeLater JavaScript SDK provides a convenient way to interact with the CallMeLater API from Node.js applications and browsers. It includes TypeScript definitions and handles authentication, request formatting, and error handling automatically.Installation
Install the SDK using npm or yarn:Copy
npm install @callmelater/sdk
Copy
yarn add @callmelater/sdk
Copy
pnpm add @callmelater/sdk
Quick Start
Basic Setup
Copy
import { CallMeLater } from "@callmelater/sdk";
// Initialize the client
const callMeLater = new CallMeLater({
apiKey: "your_api_key_here",
baseUrl: "https://api.callmelater.xyz", // optional, defaults to production
});
Environment Variables
For production applications, use environment variables:Copy
# .env
CALLMELATER_API_KEY=your_api_key_here
Copy
import { CallMeLater } from "@callmelater/sdk";
const callMeLater = new CallMeLater({
apiKey: process.env.CALLMELATER_API_KEY,
});
Scheduling Requests
Basic Scheduling
Copy
// Schedule a simple POST request
const result = await callMeLater.schedule({
targetUrl: "https://api.example.com/webhook",
targetMethod: "POST",
targetHeaders: {
"Content-Type": "application/json",
Authorization: "Bearer your-token",
},
targetBody: {
message: "Hello from the future!",
timestamp: new Date().toISOString(),
},
triggerAt: new Date(Date.now() + 3600000), // 1 hour from now
});
console.log("Scheduled:", result.scheduleId);
TypeScript Support
The SDK includes full TypeScript definitions:Copy
import {
CallMeLater,
ScheduleRequest,
ScheduleResponse,
} from "@callmelater/sdk";
const callMeLater = new CallMeLater({
apiKey: process.env.CALLMELATER_API_KEY!,
});
const scheduleData: ScheduleRequest = {
targetUrl: "https://api.example.com/webhook",
targetMethod: "POST",
targetHeaders: {
"Content-Type": "application/json",
},
targetBody: {
userId: "12345",
action: "reminder",
},
triggerAt: new Date(Date.now() + 86400000), // 24 hours from now
};
const response: ScheduleResponse = await callMeLater.schedule(scheduleData);
Convenience Methods
The SDK provides convenience methods for common scheduling patterns:Copy
// Schedule for a specific time
const tomorrow9AM = await callMeLater.scheduleAt(
new Date("2024-03-20T09:00:00Z"),
{
targetUrl: "https://api.example.com/daily-report",
targetMethod: "POST",
}
);
// Schedule with a delay
const in30Minutes = await callMeLater.scheduleIn(
30 * 60 * 1000, // 30 minutes in milliseconds
{
targetUrl: "https://api.example.com/reminder",
targetMethod: "POST",
targetBody: { message: "Meeting in 30 minutes!" },
}
);
// Schedule for tomorrow at a specific time
const tomorrowReminder = await callMeLater.scheduleTomorrow(
{ hour: 9, minute: 0 }, // 9:00 AM
{
targetUrl: "https://api.example.com/morning-reminder",
targetMethod: "POST",
}
);
Managing Schedules
Cancel Scheduled Requests
Copy
// Cancel using schedule ID
await callMeLater.cancel("sch_abc123");
// Cancel with error handling
try {
await callMeLater.cancel("sch_abc123");
console.log("Schedule cancelled successfully");
} catch (error) {
if (error.status === 404) {
console.log("Schedule not found or already executed");
} else {
console.error("Failed to cancel:", error.message);
}
}
Bulk Operations
Copy
// Schedule multiple requests
const requests = [
{
targetUrl: "https://api.example.com/user/1/reminder",
targetMethod: "POST",
triggerAt: new Date("2024-03-20T09:00:00Z"),
},
{
targetUrl: "https://api.example.com/user/2/reminder",
targetMethod: "POST",
triggerAt: new Date("2024-03-20T09:00:00Z"),
},
];
const results = await callMeLater.scheduleMany(requests);
console.log(
`Scheduled ${results.successful.length} of ${requests.length} requests`
);
// Cancel multiple schedules
const scheduleIds = ["sch_123", "sch_456", "sch_789"];
const cancelResults = await callMeLater.cancelMany(scheduleIds);
Monitoring and Analytics
Get Account Information
Copy
// Check remaining credits
const credits = await callMeLater.getCredits();
console.log(`Credits remaining: ${credits}`);
// Get usage statistics
const stats = await callMeLater.getStats({
from: new Date("2024-03-01"),
to: new Date("2024-03-31"),
});
console.log(
`Success rate: ${(
(stats.successfulInvocations / stats.totalInvocations) *
100
).toFixed(1)}%`
);
Retrieve Logs
Copy
// Get recent logs
const logs = await callMeLater.getLogs({
limit: 50,
order: "desc",
});
// Filter logs by status
const failedLogs = await callMeLater.getLogs({
status: "failed",
limit: 100,
});
// Filter by date range
const lastWeekLogs = await callMeLater.getLogs({
from: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000),
to: new Date(),
});
// Filter by target URL
const webhookLogs = await callMeLater.getLogs({
targetUrl: "https://api.example.com/webhook",
});
Error Handling
Comprehensive Error Handling
Copy
import { CallMeLaterError } from "@callmelater/sdk";
try {
const result = await callMeLater.schedule({
targetUrl: "https://api.example.com/webhook",
targetMethod: "POST",
triggerAt: new Date(Date.now() + 3600000),
});
console.log("Success:", result.scheduleId);
} catch (error) {
if (error instanceof CallMeLaterError) {
switch (error.status) {
case 401:
console.error("Invalid API key");
break;
case 402:
console.error("Insufficient credits");
break;
case 400:
console.error("Invalid request:", error.details);
break;
default:
console.error("API error:", error.message);
}
} else {
console.error("Network error:", error.message);
}
}
Retry Logic
Copy
const scheduleWithRetry = async (requestData, maxRetries = 3) => {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await callMeLater.schedule(requestData);
} catch (error) {
if (
attempt === maxRetries ||
error.status === 401 ||
error.status === 402
) {
throw error; // Don't retry auth or credit errors
}
const delay = Math.pow(2, attempt) * 1000; // Exponential backoff
await new Promise((resolve) => setTimeout(resolve, delay));
}
}
};
Advanced Usage
Custom Request Configuration
Copy
// Configure timeout and retry behavior
const callMeLater = new CallMeLater({
apiKey: process.env.CALLMELATER_API_KEY,
timeout: 10000, // 10 seconds
retries: 3,
retryDelay: 1000, // 1 second between retries
});
// Use custom headers for all requests
const callMeLater = new CallMeLater({
apiKey: process.env.CALLMELATER_API_KEY,
defaultHeaders: {
"X-Client-Version": "1.0.0",
"User-Agent": "MyApp/1.0",
},
});
Webhook Helpers
Copy
// Helper for scheduling webhook chains
class WebhookChain {
constructor(callMeLater) {
this.client = callMeLater;
this.steps = [];
}
addStep(delay, requestData) {
this.steps.push({ delay, requestData });
return this;
}
async execute(startTime = new Date()) {
const results = [];
let currentTime = new Date(startTime);
for (const step of this.steps) {
currentTime = new Date(currentTime.getTime() + step.delay);
const result = await this.client.schedule({
...step.requestData,
triggerAt: currentTime,
});
results.push(result);
}
return results;
}
}
// Usage
const chain = new WebhookChain(callMeLater)
.addStep(0, {
// Immediate
targetUrl: "https://api.example.com/start",
targetMethod: "POST",
})
.addStep(300000, {
// 5 minutes later
targetUrl: "https://api.example.com/check",
targetMethod: "GET",
})
.addStep(600000, {
// 10 minutes after start
targetUrl: "https://api.example.com/cleanup",
targetMethod: "DELETE",
});
const results = await chain.execute();
Browser Usage
The SDK also works in browsers (with appropriate CORS configuration):Copy
// In a browser environment
import { CallMeLater } from "@callmelater/sdk";
const callMeLater = new CallMeLater({
apiKey: "your_public_api_key", // Use a restricted key for browser usage
});
// Schedule from browser
document.getElementById("scheduleBtn").addEventListener("click", async () => {
try {
const result = await callMeLater.schedule({
targetUrl: "https://api.example.com/webhook",
targetMethod: "POST",
targetBody: {
source: "browser",
timestamp: new Date().toISOString(),
},
triggerAt: new Date(Date.now() + 60000), // 1 minute from now
});
console.log("Scheduled from browser:", result.scheduleId);
} catch (error) {
console.error("Failed to schedule:", error.message);
}
});
Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
apiKey | string | Required | Your CallMeLater API key |
baseUrl | string | https://api.callmelater.xyz | API base URL |
timeout | number | 30000 | Request timeout in milliseconds |
retries | number | 3 | Number of retry attempts |
retryDelay | number | 1000 | Delay between retries in milliseconds |
defaultHeaders | object | {} | Default headers for all requests |
TypeScript Definitions
Copy
interface ScheduleRequest {
targetUrl: string;
targetMethod: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD";
targetHeaders?: Record<string, string>;
targetBody?: any;
triggerAt: Date | string;
}
interface ScheduleResponse {
scheduleId: string;
invocationId: string;
message: string;
}
interface LogEntry {
invocationId: string;
scheduleId: string;
createdAt: string;
scheduledAt: string;
targetUrl: string;
targetMethod: string;
status: "scheduled" | "completed" | "failed" | "cancelled";
statusCode: number;
responseTimeMs: number;
errorMessage: string;
}
interface UsageStats {
totalInvocations: number;
successfulInvocations: number;
failedInvocations: number;
averageResponseTime: number;
timeRange: {
from: string;
to: string;
};
}

