Skip to contents
R Package Version
R Package Version

Email sending integration via Resend API for the Artalytics platform

Overview

artsend provides transactional email functionality for the Artalytics platform using the Resend API. It’s a pure email service integration without database dependencies, enabling:

  • Contact forms - Gallery visitor messages to artists
  • Notifications - Waitlist confirmations, pilot program invitations
  • Transactional emails - Whitepaper delivery, metrics access grants
  • Professional templates - Pre-built, branded HTML email designs

Installation

Install from the Artalytics GitHub organization:

# Requires GITHUB_PAT for private repos
pak::pkg_install("artalytics/artsend")

Quick Start

1. Configure API Key

Get your Resend API key from the Resend Dashboard:

# Set environment variable
Sys.setenv(ART_RESEND_KEY = "re_xxxxxxxxxxxxx")

# Verify configuration
artsend::is_resend_configured()
#> [1] TRUE

For persistent configuration, add to .Renviron:

ART_RESEND_KEY=re_xxxxxxxxxxxxx

2. Send Contact Form Email

library(artsend)

result <- send_contact_email(
  to = "artist@example.com",
  visitor_name = "John Doe",
  visitor_email = "john@example.com",
  message = "I love your artwork! Can we discuss a commission?",
  artwork_title = "Sunset Dreams",
  artwork_url = "https://cdn.artalytics.app/..."
)

if (result$success) {
  message("Email sent! ID: ", result$message_id)
} else {
  warning("Failed: ", result$error)
}

3. Handle Response

All functions return a standardized response:

list(
  success = TRUE,           # Logical indicating success
  message_id = "abc123",    # Resend message ID (if successful)
  error = NULL              # Error message (if failed)
)

Core Functions

Configuration

Function Purpose
get_resend_config() Retrieve API configuration from environment
is_resend_configured() Check if API key is set

Email Sending

Function Purpose
send_contact_email() Gallery visitor → artist contact form
send_waitlist_confirmation() Confirm artist pilot program waitlist signup
send_artist_invitation() Invite artist to join pilot program
send_whitepaper_email() Deliver whitepaper (personalized by user type)
send_investor_welcome() Investor welcome package with data room access
send_metrics_access_confirmation() Confirm metrics documentation access request
send_metrics_access_granted() Notify when metrics access is approved
send_metrics_admin_notification() Alert admin of new access request

Validation

Function Purpose
validate_email_format() Validate email address format

Environment Variables

Required

ART_RESEND_KEY Your Resend API key. Obtain from Resend Dashboard.

Production keys start with re_. Test keys start with re_test_.

# Production
Sys.setenv(ART_RESEND_KEY = "re_xxxxxxxxxxxxx")

# Development/Testing
Sys.setenv(ART_RESEND_KEY = "re_test_xxxxxxxxxxxxx")

Usage Examples

Contact Form

Send message from gallery visitor to artist:

result <- send_contact_email(
  to = "artist@example.com",
  visitor_name = "Sarah Johnson",
  visitor_email = "sarah@collector.com",
  message = "Your piece 'Urban Dreams' resonates deeply with me.",
  artwork_title = "Urban Dreams #42",
  artwork_url = "https://cdn.artalytics.app/artworks/abc123/thumb.jpg"
)

Pilot Program Workflow

# Step 1: Waitlist confirmation (immediate)
send_waitlist_confirmation(
  to = "newartist@example.com",
  artist_name = "Marcus Chen",
  waitlist_id = "wl-12345"
)

# Step 2: Invitation (after approval)
send_artist_invitation(
  to = "newartist@example.com",
  artist_name = "Marcus Chen",
  onboarding_url = "https://artalytics.app/onboarding?token=xyz789"
)

Whitepaper Delivery

Personalized by user type:

# For investors
send_whitepaper_email(
  to = "partner@vcfirm.com",
  user_type = "investor"
)

# For artists
send_whitepaper_email(
  to = "artist@example.com",
  user_type = "artist"
)

Metrics Access Request System

Three-step gated access workflow:

# Step 1: User submits request → Send confirmation
send_metrics_access_confirmation(
  to = "analyst@bank.com",
  full_name = "Jane Doe",
  request_id = "req-12345"
)

# Step 2: Notify admin for review
send_metrics_admin_notification(
  request_details = list(
    email = "analyst@bank.com",
    full_name = "Jane Doe",
    company = "Major Bank",
    role = "art_lender",
    request_id = "req-12345"
  )
)

# Step 3: After approval → Grant access
send_metrics_access_granted(
  to = "analyst@bank.com",
  full_name = "Jane Doe",
  access_instructions = "Your access code: MTR-2024-1234"
)

Documentation

Error Handling

Functions return standardized error responses:

result <- send_contact_email(...)

if (!result$success) {
  # Handle specific errors
  if (stringr::str_detect(result$error, "API key not found")) {
    # Set ART_RESEND_KEY environment variable
  } else if (stringr::str_detect(result$error, "Invalid.*email")) {
    # Validate email addresses
  } else {
    # Log error, retry, alert admin
    rdstools::log_err("Email failed: {result$error}")
  }
}

Common errors:

  • “Resend API key not found” - Set ART_RESEND_KEY environment variable
  • “Invalid recipient email format” - Use validate_email_format() to check inputs
  • “API error: …” - Check Resend dashboard for delivery status
  • “Email sending failed: …” - Network or API issues (implement retry logic)

Integration Patterns

With Database (artcore)

library(data.table)

# Create email log
email_log <- data.table(
  email_id = uuid::UUIDgenerate(),
  recipient = "artist@example.com",
  email_type = "contact_form",
  sent_utc = lubridate::now("UTC")
)

# Send email
result <- send_contact_email(...)

# Update log
email_log[, `:=`(
  resend_id = if (result$success) result$message_id else NA_character_,
  success = result$success,
  error_msg = if (is.null(result$error)) NA_character_ else result$error
)]

# Insert to database
cn <- artcore::dbc()
DBI::dbAppendTable(cn, "email_send_log", email_log)
artcore::dbd(cn)

With Shiny

# Server logic
observeEvent(input$send_btn, {
  shinybusy::show_spinner()

  result <- send_contact_email(
    to = input$artist_email,
    visitor_name = input$name,
    visitor_email = input$email,
    message = input$message
  )

  shinybusy::hide_spinner()

  if (result$success) {
    showNotification("Message sent!", type = "message")
  } else {
    showNotification(result$error, type = "error")
  }
})

Testing

Resend provides test mode for development:

# Use test API key
Sys.setenv(ART_RESEND_KEY = "re_test_xxxxxxxxxxxxx")

# Send test emails
result <- send_contact_email(
  to = "test@artalytics.app",
  visitor_name = "Test User",
  visitor_email = "dev@artalytics.app",
  message = "Test message"
)

# Test emails appear in Resend dashboard but are not actually delivered

Rate Limits

Resend free tier:

  • 100 emails/day
  • 3,000 emails/month

For production use, upgrade to a paid plan. Implement delays for batch sends:

for (email in email_list) {
  result <- send_contact_email(...)
  Sys.sleep(0.1)  # 100ms delay
}

Best Practices

  1. Validate inputs - Use validate_email_format() before sending
  2. Handle errors gracefully - Always check result$success
  3. Log all sends - Track to database for monitoring
  4. Use test keys in dev - Never send real emails from development
  5. Store API keys securely - Use environment variables, never commit
  6. Implement retries - Use exponential backoff for transient failures
  7. Monitor delivery - Check Resend dashboard regularly

Developer Guidance

Organization Standards

Review organization-wide R package standards:

Organization Agents Guide

Repository-Specific Guidance

Package-specific development instructions:

Repository Agents Guidance

Environment Setup

Development environment setup script:

Setup Script

License

See LICENSE file for details.