# 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