🔌 Dymo API in Zod

Take the Zod validation to the next level with built-in resilience system.

Overview

In order to facilitate the use of Dymo API in applications that integrate Zod, we have launched a new library specialized in projects that use Zod as a validation system. This integration includes the complete resilience system for reliable API operations.

Installation

npm install @dymo-api/zod
#or
pnpm install @dymo-api/zod
#or
yarn add @dymo-api/zod

Plugin Features

Password (Coming Soon)
Easily validate passwords in Zod
User-Agent Validation (Coming Soon)
Easily validate User-Agents in Zod

Resilience System

All Zod SDK integrations come with the built-in resilience system that provides:

  • 🔄 Automatic Retries: Configurable retry attempts with exponential backoff
  • 🚦 Rate Limiting: Intelligent tracking and management of API rate limits
  • 🛡️ Fallback Data: Automatic generation of safe fallback responses when API is unavailable
  • ⚡ Smart Error Handling: Differentiates between retry-worthy and non-retry-worthy errors

Basic Configuration

import { z } from "zod";
import DymoAPIZod from "@dymo-api/zod";

// Basic setup with resilience
const dymo = new DymoAPIZod({
  apiKey: "",
  resilience: {
      fallbackEnabled: true,    // Enable fallback data generation
      retryAttempts: 2,         // Number of additional retry attempts
      retryDelay: 1000          // Base delay in milliseconds
  }
});

// Create schema with automatic validation and resilience
const emailSchema = dymo.emailSchema();
const phoneSchema = dymo.phoneSchema();
const ipSchema = dymo.ipSchema();

Production vs Development

const productionClient = new DymoAPIZod({
  apiKey: "",
  resilience: {
      fallbackEnabled: true,     // Keep users working during outages
      retryAttempts: 2,         // 1 normal + 2 retries = 3 total attempts
      retryDelay: 500          // Faster retries for better UX
  }
});

Benefits:

  • ✅ User experience maintained during API issues
  • ✅ Balanced retry speed and reliability
  • ✅ Automatic fallback to safe responses

Usage Examples

Email Validation with Resilience

import { z } from "zod";
import DymoAPIZod from "@dymo-api/zod";

const dymo = new DymoAPIZod({
  apiKey: "",
  resilience: {
      fallbackEnabled: true,
      retryAttempts: 2,
      retryDelay: 1000
  }
});

// Create email schema with automatic resilience
const emailSchema = dymo.emailSchema();

// Use in validation pipeline
const userSchema = z.object({
  email: emailSchema,
  name: z.string().min(2)
});

try {
  const validatedUser = await userSchema.parseAsync({
      email: "[email protected]",
      name: "John Doe"
  });
  console.log("Valid user:", validatedUser.email);
} catch (error) {
  console.log("Validation failed:", error.message);
}

Phone Validation with Resilience

// Phone validation with automatic retries
const phoneSchema = dymo.phoneSchema();

const registrationSchema = z.object({
    phone: phoneSchema,
    country: z.string().length(2)
});

try {
    const validated = await registrationSchema.parseAsync({
        phone: "+34617509462",
        country: "ES"
    });
    console.log("Valid phone:", validated.phone);
} catch (error) {
    console.log("Phone validation failed:", error.message);
}

IP Validation with Resilience

// IP validation with resilience
const ipSchema = dymo.ipSchema();

const accessLogSchema = z.object({
    ip: ipSchema,
    timestamp: z.date(),
    userAgent: z.string()
});

try {
    const validated = await accessLogSchema.parseAsync({
        ip: "192.168.1.1",
        timestamp: new Date(),
        userAgent: "Mozilla/5.0..."
    });
    console.log("Valid IP:", validated.ip);
} catch (error) {
    console.log("IP validation failed:", error.message);
}

Error Handling

Monitoring Resilience

Monitor console for resilience warnings to understand API behavior and troubleshooting issues.

Common log messages:

[WARN] [Dymo API] Client xxx is rate limited. Waiting 60 seconds...
[WARN] [Dymo API] Attempt 1 failed. Retrying in 1000ms...
[WARN] [Dymo API] Request failed after 3 attempts. Using fallback data.

Fallback Behavior

When fallbackEnabled: true and all retries fail:

// The system will return structured fallback data
try {
    const result = await dymo.emailSchema().parseAsync("invalid@email");
    // If API fails completely, you get fallback data:
    // { email: "invalid@email", allow: false, reasons: ["INVALID"] }
    console.log("Fallback result:", result);
} catch (error) {
    // Only thrown if even fallback fails
    console.error("Complete failure:", error);
}

Rate Limiting

The Zod SDK automatically handles rate limiting:

// Automatic rate limit handling
const validateMultiple = async (emails: string[]) => {
    const results = await Promise.allSettled(
        emails.map(email => dymo.isValidEmail(email))
    );
    
    // The SDK will automatically:
    // 1. Track rate limits per client
    // 2. Wait for `retry-after` headers
    // 3. Not retry on 429 responses
    
    return results.map(result => 
        result.status === 'fulfilled' ? result.value : null
    );
};

Best Practices

Schema Design

// Good: Combine Zod validation with Dymo resilience
const userRegistrationSchema = z.object({
  email: dymo.emailSchema(),                    // Auto-resilience
  phone: dymo.phoneSchema(),                    // Auto-resilience
  ip: dymo.ipSchema(),                          // Auto-resilience
  password: z.string().min(8).regex(/[A-Z]/),     // Local validation
  age: z.number().min(18).max(120)              // Local validation
});

// All Dymo validations will have automatic retries and fallbacks

Benefits:

  • ✅ Automatic retries for external validations
  • ✅ Local validations are fast and don't hit API
  • ✅ Clear separation of concerns

Performance Optimization

// Cache validated emails to reduce API calls
const emailCache = new Map<string, boolean>();

const cachedEmailValidation = z.string().transform(async (email) => {
  if (emailCache.has(email)) {
      return emailCache.get(email);
  }
  
  try {
      const result = await dymo.isValidEmail(email);
      emailCache.set(email, result.allow);
      return result.allow;
  } catch (error) {
      // Cache failures for shorter time
      emailCache.set(email, false);
      setTimeout(() => emailCache.delete(email), 60000); // 1 minute
      return false;
  }
});

// Clear cache periodically
setInterval(() => emailCache.clear(), 300000); // 5 minutes

Benefits:

  • ✅ Reduced API calls and costs
  • ✅ Faster validation for repeat emails
  • ✅ Automatic cache management

Migration from Previous Version

Updating from Manual Validation

// ❌ Manual validation without resilience
import { z } from "zod";

const oldEmailSchema = z.string().transform(async (email) => {
  try {
      const response = await fetch('/api/validate', {
          method: 'POST',
          body: JSON.stringify({ email })
      });
      return response.ok;
  } catch (error) {
      // ❌ Immediate failure on network issues
      throw new Error(`Validation failed: ${error.message}`);
  }
});

// ❌ No retries, no fallbacks, poor UX

Updating Configuration

If you were using previous resilience configuration:

// Previous behavior (3 total attempts max)
resilience: { retryAttempts: 2 }  // Was: 1 normal + 2 retries = 3 total

// Same behavior now  
resilience: { retryAttempts: 2 }  // Still: 1 normal + 2 retries = 3 total

The resilience behavior remains the same - only the parameter documentation has been clarified. Your existing code will continue to work without changes.

Support

Common Issues

Getting Help

If you encounter issues with the Zod SDK resilience system:

  1. Check Console: Look for resilience warning messages
  2. Verify Configuration: Ensure resilience options are properly set
  3. Test Network: Check internet connectivity and API access
  4. Monitor Status: Check API Status Page
  5. Contact Support: Include logs and configuration details

When reporting issues, please include:

  • Your resilience configuration
  • Relevant console logs
  • Validation schema being used
  • Your API key (last 4 characters only)