Quickstart
Quickstart: create an invoice in Go
No official SDK — use net/http (stdlib)
No official Go SDK for Scell.io. The stdlib `net/http` + `encoding/json` covers 100% of needs. For production, use `context.Context` for timeouts and a configured `*http.Client` with `Transport` (retries via `hashicorp/go-retryablehttp`). The REST + snake_case JSON API maps naturally to Go structs (`json:"snake_case"` tags). Compatible with any HTTP framework (Gin, Echo, Fiber, chi).
Key facts
- Requirements: Go 1.22+
- No official SDK: stdlib `net/http` is enough
- Env var: `os.Getenv("SCELL_API_KEY")`
- HTTP: `net/http` (stdlib) or `hashicorp/go-retryablehttp`
- Expected output: typed struct with `ID`, `Status`
- Error codes: check `resp.StatusCode` + decode `errorResponse`
Code example
package main
import (
"bytes"
"crypto/rand"
"encoding/hex"
"encoding/json"
"fmt"
"net/http"
"os"
"time"
)
const API = "https://api.scell.io/api/v1"
func idempKey() string { b := make([]byte, 16); rand.Read(b); return hex.EncodeToString(b) }
func call(path string, body any) (map[string]any, error) {
data, _ := json.Marshal(body)
req, _ := http.NewRequest("POST", API+path, bytes.NewReader(data))
req.Header.Set("X-API-Key", os.Getenv("SCELL_API_KEY"))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", idempKey())
client := &http.Client{Timeout: 30 * time.Second}
resp, err := client.Do(req)
if err != nil { return nil, err }
defer resp.Body.Close()
var out map[string]any
json.NewDecoder(resp.Body).Decode(&out)
if resp.StatusCode >= 400 { return nil, fmt.Errorf("%d: %v", resp.StatusCode, out) }
return out, nil
}
func main() {
seller := map[string]any{
"siret": "12345678901234", "name": "Ma SAS", "vat_number": "FR12345678901",
"address": map[string]string{"street": "1 rue Test", "city": "Paris", "postal_code": "75001", "country": "FR"},
}
b2b, _ := call("/invoices", map[string]any{
"format": "factur-x", "profile": "EN16931", "currency": "EUR", "seller": seller,
"buyer": map[string]any{"siret": "98765432109876", "name": "Client SARL",
"address": map[string]string{"street": "2 avenue Demo", "city": "Lyon", "postal_code": "69001", "country": "FR"}},
"lines": []map[string]any{{"description": "Prestation conseil", "quantity": 1, "unit_price": 1000.0, "vat_rate": 20.0}},
})
fmt.Printf("B2B: %v (%v)\n", b2b["id"], b2b["status"])
b2c, _ := call("/invoices", map[string]any{
"format": "factur-x", "profile": "EN16931", "currency": "EUR", "seller": seller,
"buyer": map[string]any{"buyer_is_individual": true, "name": "Jean Dupont", "email": "jean@example.com",
"address": map[string]string{"street": "3 bd Client", "city": "Marseille", "postal_code": "13001", "country": "FR"}},
"lines": []map[string]any{{"description": "Abonnement", "quantity": 1, "unit_price": 49.90, "vat_rate": 20.0}},
})
fmt.Printf("B2C: %v (%v)\n", b2c["id"], b2c["status"])
sig, _ := call("/signatures", map[string]any{
"document_url": "https://example.com/contrat.pdf",
"signers": []map[string]any{{"name": "Jean Dupont", "email": "jean@example.com", "phone": "+33612345678"}},
"signature_options": map[string]any{"signature_mode": "drawn", "timezone": "Europe/Paris"},
})
fmt.Printf("Signature: %v -> %v\n", sig["id"], sig["signing_url"])
}