S
docs- Words
- 2,058
- Reading time
- 9 min
- Last crawled
- 2026-09-27
- Language
- EN
cat smashsend.com/docs/api/events.md
1. [ Home ](https://smashsend.com/) / 3. [ Docs ](https://smashsend.com/docs) / 5. [ API Reference ](https://smashsend.com/docs/api) / 7. [ Events ](https://smashsend.com/docs/api/events) The 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. What are Events? Events 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. ## Authentication & Base URL **Base URL:** `https://api.smashsend.com` All API requests must include your API key in the Authorization header. You can manage your API keys in your SMASHSEND dashboard under Settings → API. ```Authorization: Bearer sk_live_abc123...``` **Rate Limits:** • Single events: 1,000 requests per minute • Batch events: 50 requests per minute (up to 10,000 events/min) • Recommended: Use batch endpoints for high-volume tracking ## Events Endpoints ### POST/v1/events Track 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. Property Limits • Max 100 leaf keys per event • Max nesting depth: 3 levels • Max string length: 1,000 characters • Max array length: 100 items • Max payload size: 32KB per event • Arrays can only contain primitive values (no nested objects) Code Examples Install the SDK: `npm install smashsend-node` ```import { SMASHSEND } from 'smashsend-node'; const smashsend = new SMASHSEND({ apiKey: 'sk_live_abc123...'}); // Basic event trackingconst response = await smashsend.events.send({ event: 'user.signup', identify: { email: 'user@example.com' }, properties: { plan: 'premium', source: 'website', referrer: 'google' }}); console.log(`Event sent with ID: ${response.messageId}`); // Event with contact traits syncawait smashsend.events.send({ event: 'purchase.completed', identify: { email: 'customer@example.com', traits: { firstName: 'John', lastName: 'Doe', company: 'ACME Corp', isCustomer: true } }, properties: { orderId: 'order_12345', amount: 99.99, currency: 'USD', items: ['product_1', 'product_2'] }}); // Event with custom messageId for deduplicationawait smashsend.events.send({ event: 'subscription.renewed', identify: { email: 'user@example.com' }, properties: { subscriptionId: 'sub_xyz' }, messageId: 'renewal_2024_01_15_sub_xyz'}); // Event with custom timestampawait smashsend.events.send({ event: 'video.watched', identify: { email: 'viewer@example.com' }, properties: { videoId: 'vid_123', duration: 325, completed: true }, timestamp: '2024-01-15T10:30:00Z'});``` Response ```{ "success": true, "messageId": "msg_abc123xyz789", "info": "Event queued for processing"}``` ### POST/v1/events/batch Send 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. Batch Processing Benefits • Process up to 200 events per request • Reduced network overhead and faster throughput • Automatic deduplication handling • Partial success support (some events can succeed while others fail) • Up to 10,000 events per minute (50 requests × 200 events) Code Examples ```import { SMASHSEND } from 'smashsend-node'; const smashsend = new SMASHSEND({ apiKey: 'sk_live_abc123...'}); // Track multiple events at onceconst events = [ { event: 'page.view', identify: { email: 'user1@example.com' }, properties: { page: '/home', referrer: 'google' } }, { event: 'button.click', identify: { email: 'user2@example.com' }, properties: { button: 'cta', location: 'hero' } }, { event: 'form.submitted', identify: { email: 'user3@example.com', traits: { firstName: 'Jane', lastName: 'Smith' } }, properties: { formId: 'contact_us', fields: 5 } }]; const result = await smashsend.events.sendBatch(events); console.log(`Accepted: ${result.accepted}, Failed: ${result.failed}`);console.log(`Duplicates: ${result.duplicated}`); // Handle errors for failed eventsif (result.errors && result.errors.length > 0) { result.errors.forEach(error => { console.error(`Event at index ${error.index} failed:`); error.errors.forEach(err => { console.error(` - [${err.code}] ${err.message}`); }); });} // Check successful eventsif (result.events) { result.events.forEach(event => { console.log(`Event ${event.index}: ${event.messageId} (${event.status})`); });}``` Response The batch endpoint returns different HTTP status codes based on the outcome: • `200` - All events processed successfully • `207` - Partial success (some events succeeded, others failed) • `400` - All events failed ```{ "accepted": 3, "failed": 0, "duplicated": 0, "events": [ { "index": 0, "messageId": "msg_abc123", "status": "accepted" }, { "index": 1, "messageId": "msg_def456", "status": "accepted" }, { "index": 2, "messageId": "msg_ghi789", "status": "accepted" } ], "errors": []}``` Partial Success Response ```{ "accepted": 2, "failed": 1, "duplicated": 0, "events": [ { "index": 0, "messageId": "msg_abc123", "status": "accepted" }, { "index": 2, "messageId": "msg_ghi789", "status": "accepted" } ], "errors": [ { "index": 1, "errors": [ { "code": "INVALID_EMAIL", "message": "Invalid email format" } ] } ]}``` ## Event Naming Best Practices Event names should be descriptive, consistent, and follow a clear naming convention. We recommend using a hierarchical structure with dots to separate namespaces. Recommended Format `object.action` or `category.object.action` Examples ```// User eventsuser.signupuser.loginuser.logoutuser.profile_updateduser.password_changed // E-commerce eventsproduct.viewedproduct.added_to_cartproduct.removed_from_cartcart.checkout_startedpurchase.completedpurchase.refunded // Content eventsarticle.viewedarticle.sharedvideo.playedvideo.completedpdf.downloaded // SaaS eventstrial.startedsubscription.activatedsubscription.upgradedsubscription.cancelledfeature.usedworkspace.created // Engagement eventsemail.openedemail.clickedform.submittedbutton.clickedpage.viewedsearch.performed``` Naming Constraints • Max length: 60 characters • Allowed characters: alphanumeric, underscores, hyphens, dots, colons • Case-sensitive: “User.Signup” and “user.signup” are different events • Be consistent: Choose either snake\_case or camelCase and stick with it ## Event Deduplication SMASHSEND automatically handles event deduplication to prevent duplicate events from being processed. This is especially useful for handling network retries or idempotent operations. Automatic Deduplication If 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. Custom Message IDs For 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. ```// Use order ID for deduplicationawait smashsend.events.send({ event: 'purchase.completed', identify: { email: 'customer@example.com' }, properties: { orderId: 'order_12345', amount: 99.99 }, messageId: 'purchase_order_12345' // Ensures this purchase is tracked once}); // Use subscription ID + date for renewalsawait smashsend.events.send({ event: 'subscription.renewed', identify: { email: 'user@example.com' }, properties: { subscriptionId: 'sub_xyz', period: '2024-01' }, messageId: 'renewal_2024_01_sub_xyz'});``` **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. Events 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. How Traits Work • If the contact doesn't exist, they're created with the provided traits • If the contact exists, their properties are updated/merged with the traits • Traits follow the same schema as contact properties • Standard fields (firstName, lastName, etc.) and custom fields are supported ```// Create contact and track event simultaneouslyawait smashsend.events.send({ event: 'user.signup', identify: { email: 'newuser@example.com', traits: { firstName: 'John', lastName: 'Doe', company: 'ACME Corp', phone: '+1234567890', plan: 'premium', signupSource: 'landing_page' } }, properties: { referrer: 'google', campaignId: 'summer_2024' }}); // Update contact info while tracking engagementawait smashsend.events.send({ event: 'profile.completed', identify: { email: 'user@example.com', traits: { avatarUrl: 'https://example.com/avatar.jpg', countryCode: 'US', timezone: 'America/New_York', isProfileComplete: true } }}); // Track purchase and update customer statusawait smashsend.events.send({ event: 'purchase.completed', identify: { email: 'customer@example.com', traits: { isCustomer: true, lastPurchaseDate: '2024-01-15', lifetimeValue: 499.99, customerTier: 'gold' } }, properties: { orderId: 'order_12345', amount: 99.99 }});``` **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. ## Error Handling The Events API uses standard HTTP status codes and returns detailed error information to help you debug issues. Common Error Responses 400 - Bad Request ```{ "statusCode": 400, "error": "Bad Request", "message": "Event name can only contain alphanumeric characters, underscores, hyphens, dots, and colons"}``` 401 - Unauthorized ```{ "statusCode": 401, "error": "Unauthorized", "message": "Invalid API key"}``` 413 - Payload Too Large ```{ "statusCode": 413, "error": "Payload Too Large", "message": "Event payload exceeds 32KB limit"}``` 429 - Rate Limit Exceeded ```{ "statusCode": 429, "error": "Too Many Requests", "message": "Rate limit exceeded. Please retry after 60 seconds."}``` Validation Errors ```// Invalid email format{ "statusCode": 400, "error": "Bad Request", "message": "\"identify.email\" must be a valid email"} // Event name too long{ "statusCode": 400, "error": "Bad Request", "message": "Event name cannot exceed 60 characters"} // Properties too deep{ "statusCode": 400, "error": "Bad Request", "message": "Properties exceed maximum depth of 3"} // Too many events in batch{ "statusCode": 400, "error": "Bad Request", "message": "Batch cannot exceed 200 events"}``` ## Common Use Cases 1\. Product Analytics & User Behavior Tracking ```// Track feature usageawait smashsend.events.send({ event: 'feature.used', identify: { email: 'user@example.com' }, properties: { featureName: 'advanced_search', duration: 45, resultsCount: 12 }}); // Track user journeyawait smashsend.events.send({ event: 'onboarding.step_completed', identify: { email: 'newuser@example.com' }, properties: { step: 3, stepName: 'connect_integration', totalSteps: 5 }});``` 2\. E-commerce & Transaction Tracking ```// Track shopping cart eventsconst cartEvents = [ { event: 'product.added_to_cart', identify: { email: 'shopper@example.com' }, properties: { productId: 'prod_123', productName: 'Widget Pro', price: 49.99, quantity: 2 } }, { event: 'cart.checkout_started', identify: { email: 'shopper@example.com' }, properties: { cartTotal: 99.98, itemCount: 2 } }, { event: 'purchase.completed', identify: { email: 'shopper@example.com', traits: { isCustomer: true, lastPurchaseDate: new Date().toISOString() } }, properties: { orderId: 'order_789', amount: 99.98, currency: 'USD', paymentMethod: 'credit_card' } }]; await smashsend.events.sendBatch(cartEvents);``` 3\. Content Engagement Tracking ```// Track blog engagementawait smashsend.events.send({ event: 'article.viewed', identify: { email: 'reader@example.com' }, properties: { articleId: 'blog_post_42', title: 'Getting Started with Events API', category: 'tutorials', readTime: 8 }}); // Track video engagementawait smashsend.events.send({ event: 'video.completed', identify: { email: 'viewer@example.com' }, properties: { videoId: 'vid_123', title: 'Product Demo', duration: 325, percentageWatched: 95 }});``` 4\. SaaS Subscription Lifecycle ```// Track trial and subscription eventsconst subscriptionEvents = [ { event: 'trial.started', identify: { email: 'prospect@example.com', traits: { firstName: 'Jane', company: 'Startup Inc', trialEndsAt: '2024-02-01' } }, properties: { trialDays: 14, plan: 'premium' } }, { event: 'subscription.activated', identify: { email: 'prospect@example.com', traits: { isCustomer: true, plan: 'premium', subscriptionStatus: 'active' } }, properties: { planId: 'plan_premium_monthly', amount: 99.00, billingPeriod: 'monthly' } }]; await smashsend.events.sendBatch(subscriptionEvents);``` 5\. Workflow Automation Triggers Events 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. ```// Trigger welcome email workflowawait smashsend.events.send({ event: 'user.signup', identify: { email: 'newuser@example.com', traits: { firstName: 'John', signupDate: new Date().toISOString() } }}); // Trigger abandoned cart workflowawait smashsend.events.send({ event: 'cart.abandoned', identify: { email: 'shopper@example.com' }, properties: { cartValue: 249.99, itemCount: 3, items: ['product_1', 'product_2', 'product_3'] }}); // Trigger re-engagement workflowawait smashsend.events.send({ event: 'user.inactive_30_days', identify: { email: 'dormant@example.com' }, properties: { lastActiveDate: '2023-12-15', daysSinceActive: 30 }});``` ## Best Practices 1\. Use Batch Endpoints for High Volume When tracking multiple events, always use the batch endpoint. It reduces network overhead, has higher rate limits, and is more efficient. 2\. Implement Proper Error Handling Always handle errors gracefully and implement retry logic with exponential backoff for transient failures. Use the `messageId` for idempotent retries. 3\. Keep Event Names Consistent Document your event naming convention and enforce it across your team. Inconsistent event names make analytics and automation difficult. 4\. Include Relevant Context in Properties Add enough context to understand what happened without looking at other data sources. Include IDs, timestamps, and relevant metadata. 5\. Sync Contact Data with Traits Use the `identify.traits` field to keep contact information up-to-date. This eliminates the need for separate contact update calls. 6\. Monitor Your Event Volume Keep track of your event volume to stay within rate limits. If you need higher limits, contact support to discuss your use case. 7\. Use Custom Message IDs for Deduplication For critical events (like purchases or subscriptions), provide a custom `messageId` based on your unique identifier to ensure proper deduplication. 8\. Test Your Events Before deploying to production, test your events in a development environment. Verify that event names, properties, and traits are correct. ## Limits & Constraints Reference Event Limits • Event name: max 60 characters • Message ID: max 128 characters • Event payload: max 32KB • Timestamp range: ±30 years from current time Property Limits • Max leaf keys: 100 • Max nesting depth: 3 levels • Max string length: 1,000 characters • Max array length: 100 items • Arrays can only contain primitive values Batch Limits • Max events per batch: 200 • Batch payload: max 6.4MB Rate Limits • Single events: 1,000 requests/minute • Batch events: 50 requests/minute • Max events via batch: 10,000/minute (50 × 200)
