Skip to main content

Quickstart

Quickstart: create an invoice in Rust

No official SDK — use reqwest + serde_json

No official Rust SDK for Scell.io. Standard combo: `reqwest` (async/blocking HTTP client) + `serde` + `serde_json`. Compatible with Tokio and async-std. For production, add `reqwest-middleware` + `reqwest-retry` (exponential retries). JSON snake_case serialization works natively with `#[derive(Serialize, Deserialize)]`. Ideal for microservices, Tauri (desktop), or serverless (Cloudflare Workers via `worker-rs`). Target: stable Rust (2021 edition+).

Key facts

  • Requirements: Rust stable 1.75+, Cargo
  • No official SDK: `reqwest` + `serde_json`
  • Env var: `std::env::var("SCELL_API_KEY")`
  • HTTP: `reqwest` 0.12+ (with `json` feature)
  • Expected output: `serde_json::Value` or typed struct
  • Error codes: `response.error_for_status()` + `Result<T, reqwest::Error>`

Code example

// Cargo.toml: reqwest = { version = "0.12", features = ["json"] }
//             tokio = { version = "1", features = ["full"] }
//             serde_json = "1"
//             uuid = { version = "1", features = ["v4"] }
use serde_json::{json, Value};
use uuid::Uuid;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let key = std::env::var("SCELL_API_KEY")?;
    let http = reqwest::Client::new();

    let call = |path: &'static str, body: Value| {
        let http = http.clone();
        let key = key.clone();
        async move {
            let r = http.post(format!("https://api.scell.io/api/v1{}", path))
                .header("X-API-Key", &key)
                .header("Idempotency-Key", Uuid::new_v4().to_string())
                .json(&body).send().await?.error_for_status()?
                .json::<Value>().await?;
            Ok::<Value, reqwest::Error>(r)
        }
    };

    let seller = json!({
        "siret": "12345678901234", "name": "Ma SAS", "vat_number": "FR12345678901",
        "address": {"street": "1 rue Test", "city": "Paris", "postal_code": "75001", "country": "FR"}
    });

    let b2b = call("/invoices", json!({
        "format": "factur-x", "profile": "EN16931", "currency": "EUR", "seller": seller,
        "buyer": {"siret": "98765432109876", "name": "Client SARL",
            "address": {"street": "2 avenue Demo", "city": "Lyon", "postal_code": "69001", "country": "FR"}},
        "lines": [{"description": "Prestation conseil", "quantity": 1, "unit_price": 1000.0, "vat_rate": 20.0}]
    })).await?;
    println!("B2B: {} ({})", b2b["id"], b2b["status"]);

    let b2c = call("/invoices", json!({
        "format": "factur-x", "profile": "EN16931", "currency": "EUR", "seller": seller,
        "buyer": {"buyer_is_individual": true, "name": "Jean Dupont", "email": "jean@example.com",
            "address": {"street": "3 bd Client", "city": "Marseille", "postal_code": "13001", "country": "FR"}},
        "lines": [{"description": "Abonnement", "quantity": 1, "unit_price": 49.90, "vat_rate": 20.0}]
    })).await?;
    println!("B2C: {} ({})", b2c["id"], b2c["status"]);

    let sig = call("/signatures", json!({
        "document_url": "https://example.com/contrat.pdf",
        "signers": [{"name": "Jean Dupont", "email": "jean@example.com", "phone": "+33612345678"}],
        "signature_options": {"signature_mode": "drawn", "timezone": "Europe/Paris"}
    })).await?;
    println!("Signature: {} -> {}", sig["id"], sig["signing_url"]);
    Ok(())
}

See also

Your cookie preferences

We use cookies to improve your experience. Essential cookies are always active. Cookie policy.