{"id":"pg_fl8ipqlrsjdb","property_id":"prp_pfcr5h8cztsp","domain_id":"dom_gkgeprhezjg4wq","root_domain":"smashsend.com","locale":"en","url":"https://smashsend.com/docs/api/events","url_hash":"4d4e021b920017130fe7291ff0537ee25af4357f8af25f58e3bc7a6bc53452bf","path":"/docs/api/events","depth":1,"canonical_url":"https://smashsend.com/docs/api/events","canonical_page_id":null,"page_type":"docs","page_type_guess":"docs","state":"indexed","skip_reason":null,"priority":"1.4","discovered_via":"sitemap","first_seen_at":"2026-08-28T03:07:01.092Z","last_seen_at":"2026-09-27T04:10:47.779Z","http_status":200,"content_hash":"4911f2618ac5aa90c0d0b052492659fed8c6686d4dcfda54aa51140cf9814e2d","title":"SMASHSEND Events API Reference","description":"Reference documentation for the SMASHSEND Events API endpoints for tracking user events and behaviors.","author":null,"published_at":null,"modified_at":null,"word_count":2058,"reading_time_sec":561,"lang_detected":"en","images":[],"links_out":null,"markdown_source":"readability","refresh_interval":"monthly","last_fetched_at":"2026-09-27T04:09:10.843Z","next_refresh_at":"2026-10-27T04:09:10.843Z","runs_count":2,"changes_count":0,"last_changed_at":null,"fail_count":0,"last_error":null,"created_at":"2026-08-28T03:07:01.092Z","updated_at":"2026-08-28T03:07:01.092Z","inlinks":14,"inlinks_body":0,"outlinks":40,"outlinks_external":3,"anchor_terms":[],"template_score":"0.09859154929577464789","cash":"0.329537528008367109","cash_total":"0.7139211841103210548","pagerank":"0.0173913122124032","is_orphan":false,"link_confirmed":true,"discovered_wave":0,"embedded_hash":null,"embedded_at":null,"domain_name":null,"brand_color":null,"domain_rank":null,"spam_score":null,"markdown":"1.  [\n    \n    Home\n    \n    ](https://smashsend.com/)\n\n/\n\n3.  [\n    \n    Docs\n    \n    ](https://smashsend.com/docs)\n\n/\n\n5.  [\n    \n    API Reference\n    \n    ](https://smashsend.com/docs/api)\n\n/\n\n7.  [\n    \n    Events\n    \n    ](https://smashsend.com/docs/api/events)\n\nThe Events API allows you to track user events and behaviors in your SMASHSEND account. Events are powerful tools for triggering automated workflows, segmenting contacts, and understanding user engagement patterns. This API is commonly used to track product usage, user actions, and custom business events.\n\nWhat are Events?\n\nEvents represent actions or occurrences in your application (e.g., “user.signup”, “purchase.completed”, “video.watched”). Each event is associated with a contact via email and can include custom properties to capture relevant details.\n\n## Authentication & Base URL\n\n**Base URL:** `https://api.smashsend.com`\n\nAll API requests must include your API key in the Authorization header. You can manage your API keys in your SMASHSEND dashboard under Settings → API.\n\n```\nAuthorization: Bearer sk_live_abc123...\n```\n\n**Rate Limits:**\n\n• Single events: 1,000 requests per minute  \n• Batch events: 50 requests per minute (up to 10,000 events/min)  \n• Recommended: Use batch endpoints for high-volume tracking\n\n## Events Endpoints\n\n### POST/v1/events\n\nTrack a single event for a contact. This endpoint automatically creates or updates the contact if they don't exist, and enqueues the event for processing.\n\nProperty Limits\n\n• Max 100 leaf keys per event  \n• Max nesting depth: 3 levels  \n• Max string length: 1,000 characters  \n• Max array length: 100 items  \n• Max payload size: 32KB per event  \n• Arrays can only contain primitive values (no nested objects)\n\nCode Examples\n\nInstall the SDK: `npm install smashsend-node`\n\n```\nimport { SMASHSEND } from 'smashsend-node';\n\nconst smashsend = new SMASHSEND({\n  apiKey: 'sk_live_abc123...'\n});\n\n// Basic event tracking\nconst response = await smashsend.events.send({\n  event: 'user.signup',\n  identify: {\n    email: 'user@example.com'\n  },\n  properties: {\n    plan: 'premium',\n    source: 'website',\n    referrer: 'google'\n  }\n});\n\nconsole.log(`Event sent with ID: ${response.messageId}`);\n\n// Event with contact traits sync\nawait smashsend.events.send({\n  event: 'purchase.completed',\n  identify: {\n    email: 'customer@example.com',\n    traits: {\n      firstName: 'John',\n      lastName: 'Doe',\n      company: 'ACME Corp',\n      isCustomer: true\n    }\n  },\n  properties: {\n    orderId: 'order_12345',\n    amount: 99.99,\n    currency: 'USD',\n    items: ['product_1', 'product_2']\n  }\n});\n\n// Event with custom messageId for deduplication\nawait smashsend.events.send({\n  event: 'subscription.renewed',\n  identify: { email: 'user@example.com' },\n  properties: { subscriptionId: 'sub_xyz' },\n  messageId: 'renewal_2024_01_15_sub_xyz'\n});\n\n// Event with custom timestamp\nawait smashsend.events.send({\n  event: 'video.watched',\n  identify: { email: 'viewer@example.com' },\n  properties: {\n    videoId: 'vid_123',\n    duration: 325,\n    completed: true\n  },\n  timestamp: '2024-01-15T10:30:00Z'\n});\n```\n\nResponse\n\n```\n{\n  \"success\": true,\n  \"messageId\": \"msg_abc123xyz789\",\n  \"info\": \"Event queued for processing\"\n}\n```\n\n### POST/v1/events/batch\n\nSend multiple events in a single batch operation. This is the recommended endpoint for high-volume event tracking as it's more efficient and has higher rate limits.\n\nBatch Processing Benefits\n\n• Process up to 200 events per request  \n• Reduced network overhead and faster throughput  \n• Automatic deduplication handling  \n• Partial success support (some events can succeed while others fail)  \n• Up to 10,000 events per minute (50 requests × 200 events)\n\nCode Examples\n\n```\nimport { SMASHSEND } from 'smashsend-node';\n\nconst smashsend = new SMASHSEND({\n  apiKey: 'sk_live_abc123...'\n});\n\n// Track multiple events at once\nconst events = [\n  {\n    event: 'page.view',\n    identify: { email: 'user1@example.com' },\n    properties: { page: '/home', referrer: 'google' }\n  },\n  {\n    event: 'button.click',\n    identify: { email: 'user2@example.com' },\n    properties: { button: 'cta', location: 'hero' }\n  },\n  {\n    event: 'form.submitted',\n    identify: {\n      email: 'user3@example.com',\n      traits: {\n        firstName: 'Jane',\n        lastName: 'Smith'\n      }\n    },\n    properties: { formId: 'contact_us', fields: 5 }\n  }\n];\n\nconst result = await smashsend.events.sendBatch(events);\n\nconsole.log(`Accepted: ${result.accepted}, Failed: ${result.failed}`);\nconsole.log(`Duplicates: ${result.duplicated}`);\n\n// Handle errors for failed events\nif (result.errors && result.errors.length > 0) {\n  result.errors.forEach(error => {\n    console.error(`Event at index ${error.index} failed:`);\n    error.errors.forEach(err => {\n      console.error(`  - [${err.code}] ${err.message}`);\n    });\n  });\n}\n\n// Check successful events\nif (result.events) {\n  result.events.forEach(event => {\n    console.log(`Event ${event.index}: ${event.messageId} (${event.status})`);\n  });\n}\n```\n\nResponse\n\nThe batch endpoint returns different HTTP status codes based on the outcome:  \n• `200` - All events processed successfully  \n• `207` - Partial success (some events succeeded, others failed)  \n• `400` - All events failed\n\n```\n{\n  \"accepted\": 3,\n  \"failed\": 0,\n  \"duplicated\": 0,\n  \"events\": [\n    {\n      \"index\": 0,\n      \"messageId\": \"msg_abc123\",\n      \"status\": \"accepted\"\n    },\n    {\n      \"index\": 1,\n      \"messageId\": \"msg_def456\",\n      \"status\": \"accepted\"\n    },\n    {\n      \"index\": 2,\n      \"messageId\": \"msg_ghi789\",\n      \"status\": \"accepted\"\n    }\n  ],\n  \"errors\": []\n}\n```\n\nPartial Success Response\n\n```\n{\n  \"accepted\": 2,\n  \"failed\": 1,\n  \"duplicated\": 0,\n  \"events\": [\n    {\n      \"index\": 0,\n      \"messageId\": \"msg_abc123\",\n      \"status\": \"accepted\"\n    },\n    {\n      \"index\": 2,\n      \"messageId\": \"msg_ghi789\",\n      \"status\": \"accepted\"\n    }\n  ],\n  \"errors\": [\n    {\n      \"index\": 1,\n      \"errors\": [\n        {\n          \"code\": \"INVALID_EMAIL\",\n          \"message\": \"Invalid email format\"\n        }\n      ]\n    }\n  ]\n}\n```\n\n## Event Naming Best Practices\n\nEvent names should be descriptive, consistent, and follow a clear naming convention. We recommend using a hierarchical structure with dots to separate namespaces.\n\nRecommended Format\n\n`object.action` or `category.object.action`\n\nExamples\n\n```\n// User events\nuser.signup\nuser.login\nuser.logout\nuser.profile_updated\nuser.password_changed\n\n// E-commerce events\nproduct.viewed\nproduct.added_to_cart\nproduct.removed_from_cart\ncart.checkout_started\npurchase.completed\npurchase.refunded\n\n// Content events\narticle.viewed\narticle.shared\nvideo.played\nvideo.completed\npdf.downloaded\n\n// SaaS events\ntrial.started\nsubscription.activated\nsubscription.upgraded\nsubscription.cancelled\nfeature.used\nworkspace.created\n\n// Engagement events\nemail.opened\nemail.clicked\nform.submitted\nbutton.clicked\npage.viewed\nsearch.performed\n```\n\nNaming Constraints\n\n• Max length: 60 characters  \n• Allowed characters: alphanumeric, underscores, hyphens, dots, colons  \n• Case-sensitive: “User.Signup” and “user.signup” are different events  \n• Be consistent: Choose either snake\\_case or camelCase and stick with it\n\n## Event Deduplication\n\nSMASHSEND automatically handles event deduplication to prevent duplicate events from being processed. This is especially useful for handling network retries or idempotent operations.\n\nAutomatic Deduplication\n\nIf you don't provide a `messageId`, SMASHSEND generates one automatically based on the event content. The system tracks events for 24 hours to detect duplicates.\n\nCustom Message IDs\n\nFor precise control over deduplication, provide your own `messageId`. This is useful when you have a unique identifier from your system that you want to use.\n\n```\n// Use order ID for deduplication\nawait smashsend.events.send({\n  event: 'purchase.completed',\n  identify: { email: 'customer@example.com' },\n  properties: {\n    orderId: 'order_12345',\n    amount: 99.99\n  },\n  messageId: 'purchase_order_12345' // Ensures this purchase is tracked once\n});\n\n// Use subscription ID + date for renewals\nawait smashsend.events.send({\n  event: 'subscription.renewed',\n  identify: { email: 'user@example.com' },\n  properties: {\n    subscriptionId: 'sub_xyz',\n    period: '2024-01'\n  },\n  messageId: 'renewal_2024_01_sub_xyz'\n});\n```\n\n**How it works:** When a duplicate event is detected, it's marked as “duplicate” in batch responses and counted in the `duplicated` field. The event is not processed again, but the API call succeeds.\n\nEvents can automatically update contact information using the `identify.traits` field. This allows you to keep contact data in sync while tracking events, eliminating the need for separate contact update calls.\n\nHow Traits Work\n\n• If the contact doesn't exist, they're created with the provided traits  \n• If the contact exists, their properties are updated/merged with the traits  \n• Traits follow the same schema as contact properties  \n• Standard fields (firstName, lastName, etc.) and custom fields are supported\n\n```\n// Create contact and track event simultaneously\nawait smashsend.events.send({\n  event: 'user.signup',\n  identify: {\n    email: 'newuser@example.com',\n    traits: {\n      firstName: 'John',\n      lastName: 'Doe',\n      company: 'ACME Corp',\n      phone: '+1234567890',\n      plan: 'premium',\n      signupSource: 'landing_page'\n    }\n  },\n  properties: {\n    referrer: 'google',\n    campaignId: 'summer_2024'\n  }\n});\n\n// Update contact info while tracking engagement\nawait smashsend.events.send({\n  event: 'profile.completed',\n  identify: {\n    email: 'user@example.com',\n    traits: {\n      avatarUrl: 'https://example.com/avatar.jpg',\n      countryCode: 'US',\n      timezone: 'America/New_York',\n      isProfileComplete: true\n    }\n  }\n});\n\n// Track purchase and update customer status\nawait smashsend.events.send({\n  event: 'purchase.completed',\n  identify: {\n    email: 'customer@example.com',\n    traits: {\n      isCustomer: true,\n      lastPurchaseDate: '2024-01-15',\n      lifetimeValue: 499.99,\n      customerTier: 'gold'\n    }\n  },\n  properties: {\n    orderId: 'order_12345',\n    amount: 99.99\n  }\n});\n```\n\n**Note:** Contact traits are optional. If you only want to track the event without updating contact data, omit the `traits` field or pass an empty object.\n\n## Error Handling\n\nThe Events API uses standard HTTP status codes and returns detailed error information to help you debug issues.\n\nCommon Error Responses\n\n400 - Bad Request\n\n```\n{\n  \"statusCode\": 400,\n  \"error\": \"Bad Request\",\n  \"message\": \"Event name can only contain alphanumeric characters, underscores, hyphens, dots, and colons\"\n}\n```\n\n401 - Unauthorized\n\n```\n{\n  \"statusCode\": 401,\n  \"error\": \"Unauthorized\",\n  \"message\": \"Invalid API key\"\n}\n```\n\n413 - Payload Too Large\n\n```\n{\n  \"statusCode\": 413,\n  \"error\": \"Payload Too Large\",\n  \"message\": \"Event payload exceeds 32KB limit\"\n}\n```\n\n429 - Rate Limit Exceeded\n\n```\n{\n  \"statusCode\": 429,\n  \"error\": \"Too Many Requests\",\n  \"message\": \"Rate limit exceeded. Please retry after 60 seconds.\"\n}\n```\n\nValidation Errors\n\n```\n// Invalid email format\n{\n  \"statusCode\": 400,\n  \"error\": \"Bad Request\",\n  \"message\": \"\\\"identify.email\\\" must be a valid email\"\n}\n\n// Event name too long\n{\n  \"statusCode\": 400,\n  \"error\": \"Bad Request\",\n  \"message\": \"Event name cannot exceed 60 characters\"\n}\n\n// Properties too deep\n{\n  \"statusCode\": 400,\n  \"error\": \"Bad Request\",\n  \"message\": \"Properties exceed maximum depth of 3\"\n}\n\n// Too many events in batch\n{\n  \"statusCode\": 400,\n  \"error\": \"Bad Request\",\n  \"message\": \"Batch cannot exceed 200 events\"\n}\n```\n\n## Common Use Cases\n\n1\\. Product Analytics & User Behavior Tracking\n\n```\n// Track feature usage\nawait smashsend.events.send({\n  event: 'feature.used',\n  identify: { email: 'user@example.com' },\n  properties: {\n    featureName: 'advanced_search',\n    duration: 45,\n    resultsCount: 12\n  }\n});\n\n// Track user journey\nawait smashsend.events.send({\n  event: 'onboarding.step_completed',\n  identify: { email: 'newuser@example.com' },\n  properties: {\n    step: 3,\n    stepName: 'connect_integration',\n    totalSteps: 5\n  }\n});\n```\n\n2\\. E-commerce & Transaction Tracking\n\n```\n// Track shopping cart events\nconst cartEvents = [\n  {\n    event: 'product.added_to_cart',\n    identify: { email: 'shopper@example.com' },\n    properties: {\n      productId: 'prod_123',\n      productName: 'Widget Pro',\n      price: 49.99,\n      quantity: 2\n    }\n  },\n  {\n    event: 'cart.checkout_started',\n    identify: { email: 'shopper@example.com' },\n    properties: {\n      cartTotal: 99.98,\n      itemCount: 2\n    }\n  },\n  {\n    event: 'purchase.completed',\n    identify: {\n      email: 'shopper@example.com',\n      traits: {\n        isCustomer: true,\n        lastPurchaseDate: new Date().toISOString()\n      }\n    },\n    properties: {\n      orderId: 'order_789',\n      amount: 99.98,\n      currency: 'USD',\n      paymentMethod: 'credit_card'\n    }\n  }\n];\n\nawait smashsend.events.sendBatch(cartEvents);\n```\n\n3\\. Content Engagement Tracking\n\n```\n// Track blog engagement\nawait smashsend.events.send({\n  event: 'article.viewed',\n  identify: { email: 'reader@example.com' },\n  properties: {\n    articleId: 'blog_post_42',\n    title: 'Getting Started with Events API',\n    category: 'tutorials',\n    readTime: 8\n  }\n});\n\n// Track video engagement\nawait smashsend.events.send({\n  event: 'video.completed',\n  identify: { email: 'viewer@example.com' },\n  properties: {\n    videoId: 'vid_123',\n    title: 'Product Demo',\n    duration: 325,\n    percentageWatched: 95\n  }\n});\n```\n\n4\\. SaaS Subscription Lifecycle\n\n```\n// Track trial and subscription events\nconst subscriptionEvents = [\n  {\n    event: 'trial.started',\n    identify: {\n      email: 'prospect@example.com',\n      traits: {\n        firstName: 'Jane',\n        company: 'Startup Inc',\n        trialEndsAt: '2024-02-01'\n      }\n    },\n    properties: {\n      trialDays: 14,\n      plan: 'premium'\n    }\n  },\n  {\n    event: 'subscription.activated',\n    identify: {\n      email: 'prospect@example.com',\n      traits: {\n        isCustomer: true,\n        plan: 'premium',\n        subscriptionStatus: 'active'\n      }\n    },\n    properties: {\n      planId: 'plan_premium_monthly',\n      amount: 99.00,\n      billingPeriod: 'monthly'\n    }\n  }\n];\n\nawait smashsend.events.sendBatch(subscriptionEvents);\n```\n\n5\\. Workflow Automation Triggers\n\nEvents can trigger automated workflows in SMASHSEND. For example, you can create a workflow that sends a welcome email when a “user.signup” event is received, or a post-purchase follow-up when a “purchase.completed” event occurs.\n\n```\n// Trigger welcome email workflow\nawait smashsend.events.send({\n  event: 'user.signup',\n  identify: {\n    email: 'newuser@example.com',\n    traits: {\n      firstName: 'John',\n      signupDate: new Date().toISOString()\n    }\n  }\n});\n\n// Trigger abandoned cart workflow\nawait smashsend.events.send({\n  event: 'cart.abandoned',\n  identify: { email: 'shopper@example.com' },\n  properties: {\n    cartValue: 249.99,\n    itemCount: 3,\n    items: ['product_1', 'product_2', 'product_3']\n  }\n});\n\n// Trigger re-engagement workflow\nawait smashsend.events.send({\n  event: 'user.inactive_30_days',\n  identify: { email: 'dormant@example.com' },\n  properties: {\n    lastActiveDate: '2023-12-15',\n    daysSinceActive: 30\n  }\n});\n```\n\n## Best Practices\n\n1\\. Use Batch Endpoints for High Volume\n\nWhen tracking multiple events, always use the batch endpoint. It reduces network overhead, has higher rate limits, and is more efficient.\n\n2\\. Implement Proper Error Handling\n\nAlways handle errors gracefully and implement retry logic with exponential backoff for transient failures. Use the `messageId` for idempotent retries.\n\n3\\. Keep Event Names Consistent\n\nDocument your event naming convention and enforce it across your team. Inconsistent event names make analytics and automation difficult.\n\n4\\. Include Relevant Context in Properties\n\nAdd enough context to understand what happened without looking at other data sources. Include IDs, timestamps, and relevant metadata.\n\n5\\. Sync Contact Data with Traits\n\nUse the `identify.traits` field to keep contact information up-to-date. This eliminates the need for separate contact update calls.\n\n6\\. Monitor Your Event Volume\n\nKeep track of your event volume to stay within rate limits. If you need higher limits, contact support to discuss your use case.\n\n7\\. Use Custom Message IDs for Deduplication\n\nFor critical events (like purchases or subscriptions), provide a custom `messageId` based on your unique identifier to ensure proper deduplication.\n\n8\\. Test Your Events\n\nBefore deploying to production, test your events in a development environment. Verify that event names, properties, and traits are correct.\n\n## Limits & Constraints Reference\n\nEvent Limits\n\n• Event name: max 60 characters  \n• Message ID: max 128 characters  \n• Event payload: max 32KB  \n• Timestamp range: ±30 years from current time\n\nProperty Limits\n\n• Max leaf keys: 100  \n• Max nesting depth: 3 levels  \n• Max string length: 1,000 characters  \n• Max array length: 100 items  \n• Arrays can only contain primitive values\n\nBatch Limits\n\n• Max events per batch: 200  \n• Batch payload: max 6.4MB\n\nRate Limits\n\n• Single events: 1,000 requests/minute  \n• Batch events: 50 requests/minute  \n• Max events via batch: 10,000/minute (50 × 200)","storage":{"htmlKey":"stealpage/html/smashsend.com/pg_fl8ipqlrsjdb/run_sb70okmdea_i.html.gz","markdownKey":"stealpage/md/smashsend.com/pg_fl8ipqlrsjdb/run_sb70okmdea_i.md.gz"},"facets":null,"assets":[{"kind":"image","src_url":"https://smashsend.com/ogs/api-docs.jpg","r2_key":null,"alt":null,"caption":null,"width":null,"height":null,"is_hero":true,"zone":"main"},{"kind":"image","src_url":"https://smashsend.com/_next/static/media/smashsend_dark.da05b6ec.svg","r2_key":null,"alt":"SMASHSEND email marketing - The #1 Email Marketing Tool that turns emails into revenue","caption":null,"width":135,"height":30,"is_hero":false,"zone":"unknown"},{"kind":"image","src_url":"https://smashsend.com/dashboard/integrations/zapier_icon_filled.png","r2_key":null,"alt":"Zapier","caption":null,"width":20,"height":20,"is_hero":false,"zone":"nav"},{"kind":"image","src_url":"https://smashsend.com/dashboard/integrations/mailchimp_icon.png","r2_key":null,"alt":"Mailchimp","caption":null,"width":20,"height":20,"is_hero":false,"zone":"nav"},{"kind":"image","src_url":"https://smashsend.com/dashboard/integrations/webhooks_icon_gradient.png","r2_key":null,"alt":"Webhooks","caption":null,"width":20,"height":20,"is_hero":false,"zone":"nav"},{"kind":"image","src_url":"https://smashsend.com/dashboard/integrations/events.png","r2_key":null,"alt":"Events API","caption":null,"width":20,"height":20,"is_hero":false,"zone":"nav"},{"kind":"image","src_url":"https://smashsend.com/_next/image?q=75&url=%2Favatar-profile.png&w=3840","r2_key":null,"alt":"Jorge Ferreiro","caption":null,"width":null,"height":null,"is_hero":false,"zone":"nav"},{"kind":"image","src_url":"https://smashsend.com/_next/image?url=%2Favatar-profile.png&w=3840&q=75","r2_key":null,"alt":"Jorge Ferreiro","caption":null,"width":null,"height":null,"is_hero":false,"zone":"nav"},{"kind":"image","src_url":"https://smashsend.com/_next/static/media/smashsend_light.be8a3849.svg","r2_key":null,"alt":"SMASHSEND email marketing - The #1 Email Marketing Tool that turns emails into revenue","caption":null,"width":171,"height":38,"is_hero":false,"zone":"footer"},{"kind":"image","src_url":"https://smashsend.com/marketing/legal/gdpr_compliance.png","r2_key":null,"alt":"SOC2","caption":null,"width":null,"height":50,"is_hero":false,"zone":"footer"}],"shots":[{"viewport":"mobile","width":390,"height":844,"r2_key":"stealpage/shots/smashsend.com/pg_fl8ipqlrsjdb/run_sb70okmdea_i-mobile.png","phash":"26d088a0c830a492","visual_delta":0,"captured_at":"2026-09-27T04:09:15.112Z"},{"viewport":"desktop","width":1440,"height":900,"r2_key":"stealpage/shots/smashsend.com/pg_fl8ipqlrsjdb/run_sb70okmdea_i-desktop.png","phash":"86634369486060c1","visual_delta":0,"captured_at":"2026-09-27T04:09:14.922Z"},{"viewport":"mobile","width":390,"height":844,"r2_key":"stealpage/shots/smashsend.com/pg_fl8ipqlrsjdb/run_q-b9wzlpaata-mobile.png","phash":"26d088a0c830a492","visual_delta":null,"captured_at":"2026-08-28T03:12:05.741Z"},{"viewport":"desktop","width":1440,"height":900,"r2_key":"stealpage/shots/smashsend.com/pg_fl8ipqlrsjdb/run_q-b9wzlpaata-desktop.png","phash":"86634369486060c1","visual_delta":null,"captured_at":"2026-08-28T03:12:05.029Z"}],"history":[{"id":"run_sb70okmdea_i","started_at":"2026-09-27T04:09:10.836Z","http_status":200,"fetcher":"direct","changed":false,"diff":{"added":0,"removed":58,"similarity":null},"word_count":2058},{"id":"run_q-b9wzlpaata","started_at":"2026-08-28T03:11:55.122Z","http_status":200,"fetcher":"direct","changed":false,"diff":null,"word_count":2116}],"citedBy":[]}