Copy
type SendStatus = 'pending' | 'sent' | 'failed';
interface SendResponse {
sendId: string; // e.g., "sends_..."
status: SendStatus; // final status after send attempt
messageId?: string; // provider message id (opaque)
reused?: boolean; // true if idempotency key reused an existing send
}
Copy
type EventType = 'sent' | 'delivered' | 'bounced' | 'complained' | 'opened' | 'clicked' | 'delayed';
interface SendRow {
_id: string; // send id
toEmail: string;
subject: string;
status: SendStatus;
idempotencyKey: string;
createdAt: number; // ms epoch
updatedAt: number; // ms epoch
}
interface MessageRow {
sendId: string;
provider: string; // internal provider key
fromEmail: string;
toEmail?: string;
fromName?: string;
replyTo?: string;
subject?: string;
html?: string;
text?: string;
headers?: Record<string, unknown>;
feedbackId?: string; // e.g., "send-<sendId>" or "campaign-<id>"
providerMessageId?: string;
createdAt: number;
}
interface EventRow {
sendId: string;
type: EventType;
ts: number; // ms epoch
providerMessageId?: string;
metadata?: unknown; // normalized provider payload
}
interface TimelineResponse {
send: SendRow;
messages: MessageRow[];
events: EventRow[]; // newest first
}
