flowglad 0.1.0

Rust SDK for FlowGlad - Open source billing infrastructure
Documentation
# FlowGlad SDK Examples

This directory contains practical examples demonstrating how to use the FlowGlad Rust SDK.

## Prerequisites

All examples require a FlowGlad API key. You can get one by signing up at [FlowGlad](https://flowglad.com).

Set your API key as an environment variable:

```bash
export FLOWGLAD_API_KEY=sk_test_your_key_here
```

## Running Examples

Run any example using:

```bash
cargo run --example <example_name>
```

For example:

```bash
FLOWGLAD_API_KEY=sk_test_... cargo run --example basic_customers
```

## Available Examples

### 1. Basic Customers (`basic_customers.rs`)

**What it demonstrates:**
- Creating a customer
- Retrieving a customer by external ID
- Updating customer information
- Listing all customers
- Getting billing details

**Run with:**
```bash
FLOWGLAD_API_KEY=sk_test_... cargo run --example basic_customers
```

**Key concepts:**
- External ID vs Internal ID (use external_id for GET/UPDATE)
- Builder pattern for creating customers
- The Customer resource API

**Code snippet:**
```rust
// Create a customer
let customer = client.customers().create(
    CreateCustomer::new("user_123", "Jane Doe")
        .email("jane@example.com")
        .phone("+1-555-0123")
).await?;

// Retrieve by external_id (not customer.id!)
let retrieved = client.customers().get("user_123").await?;

// Update customer
let updated = client.customers().update(
    "user_123",
    UpdateCustomer::new()
        .name("Jane Smith")
        .email("jane.smith@example.com")
).await?;
```

### 2. Customer Metadata (`customer_metadata.rs`)

**What it demonstrates:**
- Adding metadata using the builder pattern
- Creating metadata separately and attaching it
- Updating metadata
- Working with complex nested metadata structures

**Run with:**
```bash
FLOWGLAD_API_KEY=sk_test_... cargo run --example customer_metadata
```

**Key concepts:**
- Metadata is a `HashMap<String, serde_json::Value>`
- Can store strings, numbers, booleans, arrays, or objects
- Use metadata to avoid custom database fields
- Metadata is returned with customer objects

**Code snippet:**
```rust
// Using builder pattern
let customer = client.customers().create(
    CreateCustomer::new("user_123", "Alice")
        .metadata("subscription_tier", json!("premium"))
        .metadata("max_seats", json!(25))
        .metadata("features", json!(["api_access", "sso"]))
).await?;

// Pre-building metadata
let mut metadata = Metadata::new();
metadata.insert("plan_id".to_string(), json!("plan_abc123"));
metadata.insert("trial_ends_at".to_string(), json!("2025-12-31"));

let customer = client.customers().create(
    CreateCustomer::new("user_456", "Bob")
        .with_metadata(metadata)
).await?;
```

### 3. Error Handling (`error_handling.rs`)

**What it demonstrates:**
- Configuration errors
- API errors (404, 400, etc.)
- Network errors and timeouts
- Rate limiting
- Practical error handling patterns

**Run with:**
```bash
FLOWGLAD_API_KEY=sk_test_... cargo run --example error_handling
```

**Key concepts:**
- Error enum is `#[non_exhaustive]` - use catch-all pattern
- Different error types: Api, Network, RateLimit, Config, Serialization, Unknown
- Automatic retries on 5xx errors with exponential backoff
- Custom timeout configuration

**Code snippet:**
```rust
match client.customers().get("nonexistent").await {
    Ok(customer) => {
        println!("Found: {}", customer.id);
    }
    Err(Error::Api { status, message, code }) => {
        eprintln!("API error ({}): {}", status, message);
        match status {
            404 => eprintln!("Resource not found"),
            401 => eprintln!("Check your API key"),
            429 => eprintln!("Rate limited - slow down"),
            _ => eprintln!("Check FlowGlad status"),
        }
    }
    Err(Error::Network(e)) => {
        eprintln!("Network error: {}", e);
    }
    Err(Error::RateLimit { retry_after }) => {
        eprintln!("Rate limited!");
        if let Some(duration) = retry_after {
            eprintln!("Retry after: {:?}", duration);
        }
    }
    Err(e) => {
        // Catch-all for any future error variants
        eprintln!("Error: {}", e);
    }
}
```

## Common Patterns

### Creating a Client

```rust
use flowglad::{Client, Config};

// Simple configuration
let config = Config::new("sk_test_...");
let client = Client::new(config)?;

// From environment variable
let config = Config::from_env()?;
let client = Client::new(config)?;

// Advanced configuration
let config = Config::builder()
    .api_key("sk_test_...")
    .timeout(Duration::from_secs(60))
    .max_retries(5)
    .build()?;
let client = Client::new(config)?;
```

### Working with External IDs

**IMPORTANT:** FlowGlad uses external IDs (YOUR system's IDs) for all GET, UPDATE, and DELETE operations.

```rust
// ✅ Correct
let customer = client.customers().create(
    CreateCustomer::new("user_123", "Jane")  // user_123 is YOUR ID
).await?;

// customer.id is "cus_xyz" (FlowGlad's internal ID)
// customer.external_id is "user_123" (your ID)

// Use external_id for GET/UPDATE, not customer.id
let retrieved = client.customers().get("user_123").await?;  // ✅
// NOT: client.customers().get(&customer.id)  // ❌ Will return 404
```

### Builder Pattern

All create and update operations use the builder pattern:

```rust
CreateCustomer::new("user_123", "Jane Doe")
    .email("jane@example.com")
    .phone("+1-555-0123")
    .metadata("key", json!("value"))
```

## Testing

All examples are designed to be safe to run repeatedly:
- They generate unique identifiers using timestamps
- They create new customers each time
- They don't modify existing production data (assuming you use test keys)

## Tips

1. **Always use test keys for examples**: Start with `sk_test_` keys
2. **Check the output**: Examples print detailed information about operations
3. **Read the source**: Each example is heavily commented
4. **Experiment**: Modify the examples to test your use cases
5. **Error handling**: Always handle errors in production code (see `error_handling.rs`)

## Need Help?

- **SDK Documentation**: Run `cargo doc --open` to view full documentation
- **API Reference**: https://docs.flowglad.com/api-reference
- **FlowGlad Dashboard**: https://app.flowglad.com
- **Context for AI Models**: See `CLAUDE_CONTEXT.md` for detailed implementation notes

## Contributing

Found a useful pattern? Consider adding a new example! Examples should:
- Be self-contained and runnable
- Include clear comments explaining each step
- Use the environment variable pattern for API keys
- Generate unique identifiers to avoid conflicts
- Print helpful output showing what's happening