GrowLeafy ONE IDENTITY. PROTECT EVERYTHING.
GrowLeafy API

One API for the
physical world.

Identities, assets, identifiers, relationships, organizations, webhooks and usage — machine access through scoped credentials, never a human login. First call in under 10 minutes.

OpenAPI specification Enterprise portal
Quick start

From zero to your first asset

1 · Create an organization

Sign in normally, then create your organization — the tenant for everything that follows.

POST /api/v1/organizations { "name": "ABC Battery", "type": "oem" }

2 · Generate API credentials

One application per integration; secrets are shown once and stored hashed.

POST /api/v1/partner-api/token { "client_id": "pk_…", "client_secret": "…" } → { "token": "…", "token_type": "Bearer" }

3 · Create identities

Bulk pre-provision with external-reference idempotency — resending a batch creates nothing twice.

POST /api/v1/organizations/{org}/assets/bulk { "count": 2000, "asset_type": "battery", "batch_id": "BAT-2026-09", "manufacturer": "ABC" }

4 · Attach identifiers & relationships

Many QR/NFC/serial identifiers → one identity. Link systems, components and organizations.

POST /api/v1/organizations/{org}/assets/{u}/identifiers { "type": "nfc", "token": "04:AB:..", "purpose": "service" } POST /api/v1/organizations/{org}/assets/{u}/organizations { "relationship_type": "INSTALLER" }

5 · Subscribe to events

Signed, replay-protected webhooks with topic + per-asset filtering.

POST /api/v1/organizations/{org}/webhook-endpoints { "url": "https://…", "topics": ["asset.activated"] }

6 · Meter & verify

Value-based usage per organization, idempotent by reference.

GET /api/v1/organizations/{org}/usage → { active_assets, meters: [...] }
Authentication & security

Who is calling, and what can they do?

Machine access

Client credentials → scoped Bearer token. Organization comes from the credential — never from the request body.

Scopes (least privilege)

  • identity:read · identity:write
  • assets:read · assets:write
  • relationship:read · relationship:create
  • fleet / drivers / custody / maintenance
  • webhooks:read · webhooks:write
  • usage:read · billing:read · warranty:create · service:write

The full surface (live)

  • POST /organizations/{o}/assets/bulk — factory provisioning
  • POST /assets/{u}/identifiers — many QR/NFC/serial → one identity
  • POST /assets/{u}/allocate · GET /inventory — supply chain
  • GET /assets/{u}/passport · /network · /dpp
  • POST /assets/{u}/warranty · POST /recalls
  • POST /assets/{u}/organizations · /grants + consent
  • GET /customers · GET /console — connected users + factory KPIs
  • POST /identifiers/resolve — universal resolution
  • GET /scim/v2/Users — directory provisioning

Every response

X-Request-ID header + machine-readable errors {error:{code,message,request_id}}. Idempotency-Key on writes; 429 with Retry-After.

Tenant isolation

Organization A can never read or modify Organization B — enforced at the middleware, service and query layers, not the UI.

Webhook verification

Signatures are computed over the raw payload: sha256=HMAC_SHA256(timestamp + "." + raw_body, webhook_secret) with X-GrowLeafy-Event / -Delivery / -Timestamp / -Request-ID / -Signature headers. Reject timestamps outside your tolerance; delivery IDs are globally unique.

Events

  • identity.created · identity.activated
  • asset.created · asset.updated · asset.transferred
  • identifier.attached · identifier.replaced
  • service.request_created · service.completed
  • maintenance.created · custody.changed
  • qr.activated · qr.revoked · qr.replaced

Delivery

Retry with exponential backoff, delivery ledger, asset-filtered subscriptions, transactional outbox for reliability.

Role playbooks

One API — every role's workflow

🏭 Manufacturer

Identity at the factory → distribute → warranty → recall → authorized events.

POST /organizations/{org}/assets/bulk ← 1M identities POST /assets/{u}/allocate ← → distributor POST /assets/{u}/warranty { policy, ends_at } POST /recalls { title, batch_id } GET /customers · GET /console ← factory KPIs

🚚 Distributor

Receive authorized inventory, transfer onward — custody changes, identity never does.

GET /organizations/{org}/inventory ← my received stock POST /assets/{u}/allocate { target_org_id, relationship_type: "INSTALLER" } ← onward GET /assets/{u}/network ← who's connected

🔧 Installer / Dealer

Record installation, link components, hand the asset to the owner.

POST /assets/{u}/organizations { relationship_type: "INSTALLER" } POST /assets/{u}/link { related_uuid, relation: "INSTALLED_IN" } POST /assets/{u}/connections { user_id, relationship_type: "OWNER", consent_required: true }

🛠 Service provider

Asset-contextual cases, append-only timeline, provider-owned pricing.

GET /customers ← asset-mediated only POST /service-cases/{case} { status: "accepted"|"scheduled"| "in_service"|"completed" } GET /assets/{u}/passport ← authorized window

🛡 Insurer

A participant, never an owner: authorized domains only, consent-gated.

POST /assets/{u}/grants { data_domain: "insurance", purpose: "INSURANCE", expires_at: "…" } GET /assets/{u}/organizations ← active windows POST /grants/{grant}/consent ← owner-side

🧑 User

Your physical world + your network — one account, consent in your hands.

GET /me/connections ← my organizations POST /connections/{id}/respond { decision } POST /assets/{uuid}/service-cases { category: "battery inspection" } PATCH /assets/{uuid} { privacy_settings } ← per-field
Industry examples

Same engine, every industry

🔋 Battery

Bulk provision 1M → serial+batch → distributor inventory → installed_in vehicle/solar → owner claims → service cases → warranty/recall → recycler window.

☀️ Solar

Site → array → panels → inverter → battery → gateway as one graph (COMPONENT_OF); each panel keeps its own identity, warranty and DPP record.

🚗 Automotive

Vehicle with windshield QR + service QR + NFC + VIN — many identifiers, one identity; components replace historically (battery A removed_from, battery B installed_in).

📦 Logistics

Container/shipment/package as related levels; custody events with effective dates; warehouse/carrier/customer each see their window.

🩺 Medical

Equipment identity strictly separate from patient/clinical data — service partners see authorized maintenance data only.

🏢 Facilities & rental

Building → floor → room → equipment graph; rental = owner ≠ custodian — custody changes, identity stays.

Error catalogue & limits

Standard errors

  • VALIDATION_ERROR · UNAUTHENTICATED
  • FORBIDDEN · NOT_FOUND · RATE_LIMITED
  • SCOPE_REQUIRED · EXISTING_ASSET_FOUND
  • ASSET_NOT_CLAIMED · INTERNAL_ERROR

Limits & idempotency

  • Bulk provisioning: 2,000/call (queued millions pipeline next)
  • Idempotency-Key on writes — repeat = original result
  • 429 with Retry-After; scopes are least-privilege
  • SCIM: org-scoped token, 60 req/min

Sandbox

Create a sandbox organization for experiments — same API, same tooling, isolated from production. Credentials are environment-scoped; secrets shown once.

Build on the identity layer.

Sandbox organizations keep experiments away from production — same API, same tooling, zero risk.

Open the enterprise portal Read the OpenAPI