Specification v0.2.0
The normative requirements and API contracts that define interoperable localLOOP implementations. No public pilots or deployments yet.
Included in this spec
LOOP Specification v0.2.0
Local Optimization with Overflow Protocol
Draft Specification - Request for Comments
Version: 0.2.0 Status: Draft (DPP-Compatible Lab Baseline) Updated: March 2026 License: CC BY-SA 4.0
Table of Contents
- Introduction
- Terminology
- Protocol Overview
- MaterialDNA Specification
- LoopCoin Specification
- LoopSignal Specification
- LoopCost Calculation
- API Endpoints
- Federation Protocol
- Security Considerations
- Implementation Guidance
- Examples
- Future Considerations
- References
Abstract
The Local Optimization with Overflow Protocol (LOOP) enables federated material exchange between autonomous municipal nodes while preserving local economic sovereignty. This specification defines the core protocol for inter-city communication, material identification, economic settlement, and democratic governance mechanisms that together create a planetary-scale circular economy infrastructure.
LOOP allows cities to:
- Track materials using universal identifiers (MaterialDNA)
- Track products using DPP-compatible identifiers (ProductDNA)
- Issue local currencies with defined properties (LoopCoin)
- Express community trade preferences (LoopSignal)
- Calculate optimal material routing (LoopCost)
- Settle transactions across municipal boundaries
This document specifies LOOP version 0.2.0, focusing on core functionality required for basic interoperability, DPP-compatible extensions, and lab-only demos.
1. Introduction
1.1 Background
Current material recovery systems operate in isolation, leading to suboptimal resource allocation and missed opportunities for circular economy implementation. Cities lack infrastructure to coordinate material flows while maintaining local control over their economies.
LOOP addresses these challenges by providing:
- Federated architecture that preserves local autonomy
- Economic incentives for circular behaviors
- Democratic mechanisms for community preferences
- Transparent routing algorithms
- Open standards for interoperability
1.2 Goals
LOOP aims to:
- Enable any city to participate in global material exchange
- Preserve local economic sovereignty
- Optimize material flows through market mechanisms
- Incorporate democratic community preferences
- Create transparent, auditable transactions
- Support multiple implementation approaches
1.3 Scope
This specification covers:
- Protocol message formats
- Required API endpoints
- Calculation methodologies
- Settlement procedures
- Security requirements
This specification does NOT cover:
- Local implementation details
- User interface requirements
- Specific database schemas
- Local governance procedures
- Business logic beyond protocol requirements
1.4 Conformance
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
2. Terminology
Node: An autonomous LOOP implementation, typically operated by a municipality
MaterialDNA: Globally unique identifier for any material item or batch
ProductDNA: Globally unique identifier for a product or product batch, referencing constituent MaterialDNA entries
LoopCoin (LC): Local digital currency with expiry properties
LoopSignal: Community-expressed preference percentage for material categories
LoopCost: Total cost including base price, export/import penalties, and distance
Federation: Network of interconnected LOOP nodes
Settlement: Process of confirming material transfer and payment
Penalty: Additional cost applied when materials cross city boundaries
Overflow: Routing mechanism when local demand is insufficient
2.1 Key Concepts
The following expanded definitions constitute the canonical reference for LOOP's six core concepts. All other documents (glossary, website, guides) derive their definitions from this subsection.
LOOP (Local Optimization with Overflow Protocol). LOOP is an open, federated protocol standard for tracking material and product flows between autonomous municipal nodes. It enables cities to register materials and products, publish surplus and demand signals, compute transfer costs, and settle cross-boundary transactions — all while preserving local data sovereignty and economic autonomy. The protocol is built on four foundational primitives (MaterialDNA, ProductDNA, LoopCoin, LoopSignal) and one derived metric (LoopCost), each defined below.
MaterialDNA. MaterialDNA is a globally unique digital identity assigned to a physical material or material batch within the LOOP protocol. Each MaterialDNA record captures the material's composition, category, origin, quantity, quality metrics, and chain of custody, providing a complete provenance trail from source through every subsequent transfer. MaterialDNA serves as the primary identifier in the protocol's material lifecycle: registration, offer, match, and transfer. It is distinct from ProductDNA, which operates at the product layer; a single product may reference multiple MaterialDNA entries as its constituent materials.
ProductDNA.
ProductDNA is a globally unique digital identity for a finished or semi-finished product (or product batch) within the LOOP protocol. It is aligned with the EU Digital Product Passport framework (ESPR Art. 9–10) and captures product category, name, condition, manufacturer, model, manufacture year, functional status, and lifecycle stage. A ProductDNA entry MAY reference zero or more MaterialDNA identifiers via a composition link (material_ids), enabling full traceability from product to constituent materials. ProductDNA is the product layer in LOOP's two-tier identity hierarchy; MaterialDNA is the composition layer. The same lifecycle flow (Offer, Match, Transfer) applies to both MaterialDNA and ProductDNA entities.
LoopCoin (LC). LoopCoin is a node-issued local digital currency used to settle material and product transfers between nodes in the federation. Each node defines its own LoopCoin configuration, including a currency code, backing currency, exchange rate, local-use bonus, expiry period, decay rate, maximum issuance, and reserve ratio. LoopCoin's built-in expiry and decay rules incentivise local circulation and prevent indefinite hoarding. When transfers cross node boundaries, LoopCoin settlement occurs through inter-node clearing, converting between each node's local currency at the declared exchange rate. LoopCoin is the unit of account for all LoopCost calculations.
LoopSignal. A LoopSignal is a community-expressed preference signal for material categories, published by a node. Each signal is a percentage (between 0.0 and 1.0) that represents the community's desire to retain or attract materials in a given category — higher values indicate stronger preference. LoopSignals are set through democratic voting (LoopVote) and are subject to constraints: changes MUST NOT exceed 0.10 per voting period, and signals MUST apply equally to imports and exports. LoopSignals serve as inputs to the LoopCost calculation (§7), where they determine the export and import penalty components. A LoopSignal is the preference input; LoopCost is the computed outcome.
LoopCost.
LoopCost is the total routing cost for any material or product transfer between nodes, computed according to the formula: LoopCost = BasePrice + ExportPenalty + ImportPenalty + DistanceCost. The BasePrice is the offered price in LoopCoins. The ExportPenalty equals BasePrice × OriginLoopSignal (applied when a material or product leaves its origin node). The ImportPenalty equals BasePrice × DestinationLoopSignal (applied when a material or product enters the destination node). The DistanceCost equals Distance_km × 0.02 LC/km. For local transactions (same node), only the BasePrice applies, making intra-node exchanges structurally cheaper than cross-boundary ones. This cost asymmetry keeps circular value circulating close to its source while still permitting inter-node trade when economically justified. The full calculation methodology and settlement distribution are specified in §7.
3. Protocol Overview
3.1 Architecture
LOOP follows a federated architecture where each city operates an autonomous node. Nodes communicate using HTTPS and JSON-LD messages.
3.2 Core Components
Each LOOP node MUST implement:
- Material Registry: Tracks MaterialDNA within node jurisdiction
- Product Registry: Tracks ProductDNA (DPP-compatible product identifiers) within node jurisdiction
- Currency Engine: Manages LoopCoin issuance and transfers
- Signal Governor: Handles democratic voting on preferences
- Routing Calculator: Computes optimal destinations using LoopCost
- Settlement Handler: Confirms and records transactions
3.3 Communication Flow
Standard material exchange flow:
- Registration: Material registered with unique MaterialDNA
- Announcement: Availability broadcast to federated nodes
- Discovery: Interested nodes discover available materials
- Calculation: Each node calculates their LoopCost
- Offer: Nodes submit offers to material owner
- Selection: Optimal match determined by lowest/highest LoopCost
- Settlement: Transaction executed and confirmed
- Confirmation: Final state broadcast to network
3.4 Data Format
All protocol messages MUST use:
- Transport: HTTPS (TLS 1.3 or higher)
- Content-Type:
application/ld+json - Encoding: UTF-8
- Timestamps: ISO 8601 format in UTC
3.5 Minimal Interop Flow v0.2.0
This subsection defines the smallest interoperable flow required for lab-only demonstrations. It is intentionally minimal, scoped to controlled environments, and does not represent a public pilot.
Flow sequence
- MaterialDNA is registered by a node.
- Offer is published for that material.
- Match is accepted between two nodes.
- Transfer is completed and recorded.
Required entities
All payloads MUST include @context, @type, and schema_version.
Emitters targeting the v0.2.0 baseline SHOULD set schema_version to 0.2.0.
Receivers SHOULD accept additive minor/patch versions when unknown fields can be preserved or ignored without data loss.
Payloads using schema_version: "0.1.1" remain valid against v0.2.0 schemas (backward compatible).
- MaterialDNA
Schema:
https://local-loop-io.github.io/projects/loop-protocol/schemas/v0.2.0/material-dna.schema.json - ProductDNA
Schema:
https://local-loop-io.github.io/projects/loop-protocol/schemas/v0.2.0/product-dna.schema.json - Offer
Schema:
https://local-loop-io.github.io/projects/loop-protocol/schemas/v0.2.0/offer.schema.json - Match
Schema:
https://local-loop-io.github.io/projects/loop-protocol/schemas/v0.2.0/match.schema.json - Transfer
Schema:
https://local-loop-io.github.io/projects/loop-protocol/schemas/v0.2.0/transfer.schema.json
Note: v0.1.1 schema URLs remain available for backward compatibility. See RFC-0003 for the versioning policy.
Data minimization
To remain GDPR-aligned for lab demos, payloads MUST NOT include personal data. Node identifiers, city names, and organization identifiers are permitted; emails, phone numbers, and names are not permitted in these entities.
Additive compatibility extensions
To improve forward compatibility with emerging regulatory data requirements, implementations MAY attach additive extension blocks such as passport, classification, and traceability.
These extensions:
- MUST remain optional in the v0.1.1 baseline
- MUST NOT weaken the data-minimization rule above
- SHOULD use the canonical JSON-LD context or explicit namespaced terms
- SHOULD preserve unknown fields when relaying payloads between nodes
4. MaterialDNA Specification
4.1 Identifier Format
MaterialDNA identifiers MUST follow this pattern:
MAT-{COUNTRY}-{CITY}-{YEAR}-{CATEGORY}-{UNIQUE}
Where:
MAT: Fixed prefix identifying a materialCOUNTRY: ISO 3166-1 alpha-2 codeCITY: Three-letter city code (locally defined)YEAR: Four-digit year of registrationCATEGORY: Material category codeUNIQUE: Alphanumeric unique identifier (min 6 characters)
Example:
MAT-DE-MUC-2025-PLASTIC-B847F3
4.2 MaterialDNA Object
{
"@context": "https://local-loop-io.github.io/projects/loop-protocol/contexts/loop-v0.1.1.jsonld",
"@type": "MaterialDNA",
"schema_version": "0.1.1",
"id": "MAT-DE-MUC-2025-PLASTIC-B847F3",
"category": "plastic-pet",
"quantity": {
"value": 1000,
"unit": "kg"
},
"quality": 0.95,
"origin_city": "Munich",
"current_city": "Munich",
"location": {
"lat": 48.1351,
"lon": 11.5820,
"address": "Recycling Center Munich"
},
"available_from": "2025-05-27T10:00:00Z",
"expires": "2025-06-03T10:00:00Z",
"certifications": ["food-grade", "iso-14001"],
"images": ["https://example.com/material-photo.jpg"],
"metadata": {
"source": "consumer-collection",
"batch_number": "2025-W22-01",
"notes": "Clean, sorted PET bottles"
}
}
4.3 Required Fields
schema_version: Schema version (v0.1.1)id: Unique MaterialDNA identifiercategory: Standardized category codequantity: Amount and unitorigin_city: Registering citycurrent_city: Current custodian cityavailable_from: When material becomes available
4.4 Standard Categories
Base categories (extensible by communities):
plastics/
plastic-pet # Polyethylene terephthalate
plastic-hdpe # High-density polyethylene
plastic-pvc # Polyvinyl chloride
plastic-ldpe # Low-density polyethylene
plastic-pp # Polypropylene
plastic-ps # Polystyrene
plastic-mixed # Mixed/unsorted plastics
metals/
metal-steel # Steel and iron
metal-aluminum # Aluminum
metal-copper # Copper
metal-mixed # Mixed metals
organics/
organic-food # Food waste
organic-garden # Garden waste
organic-wood # Wood waste
glass/
glass-clear # Clear glass
glass-brown # Brown glass
glass-green # Green glass
glass-mixed # Mixed glass
paper/
paper-clean # Clean paper
paper-newsprint # Newspapers
cardboard # Cardboard
paper-mixed # Mixed paper
textiles/
textile-cotton # Cotton
textile-wool # Wool
textile-synthetic # Synthetic fabrics
textile-mixed # Mixed textiles
electronics/
ewaste-computers # Computers and peripherals
ewaste-phones # Mobile phones
ewaste-batteries # Batteries
ewaste-mixed # Mixed electronics
4.5 ProductDNA Specification
4.5.1 Overview
ProductDNA represents the product layer in LOOP's two-tier hierarchy: materials compose products. While MaterialDNA tracks raw or processed materials (e.g., plastic-hdpe, metal-copper), ProductDNA tracks finished or semi-finished products (e.g., office desks, laptops) that contain those materials.
This separation aligns with:
- EU ESPR (Art. 9-10): Digital Product Passports are defined at the product level
- UNTP ProductPassport: Materials are nested inside product passports
- GS1/EPCIS: Trade items (products) are the primary tracking unit
4.5.2 Hierarchy
MaterialDNA (composition layer) ProductDNA (product layer, DPP-facing)
├── category: plastic-hdpe ├── product_category: electronics-laptop
├── quantity: 2kg ├── material_ids: [MAT-DE-MUC-2025-PLASTIC-..., ...]
├── origin_city: Munich ├── condition: good
└── passport (DPP fields) ├── passport (DPP fields, ESPR-aligned)
└── lifecycle_stage: in-use
A ProductDNA entry MAY reference zero or more MaterialDNA entries via material_ids. This composition link enables traceability from product to constituent materials.
4.5.3 Identifier Format
ProductDNA identifiers MUST follow this pattern:
PRD-{COUNTRY}-{CITY}-{YEAR}-{CATEGORY}-{UNIQUE}
Where:
PRD: Fixed prefix identifying a productCOUNTRY: ISO 3166-1 alpha-2 codeCITY: Three-letter city codeYEAR: Four-digit year of registrationCATEGORY: Product category keywordUNIQUE: Alphanumeric unique identifier (min 6 characters)
Example:
PRD-DE-MUC-2025-DESK-F4A7B2
4.5.4 ProductDNA Object
{
"@context": "https://local-loop-io.github.io/projects/loop-protocol/contexts/loop-v0.2.0.jsonld",
"@type": "ProductDNA",
"schema_version": "0.2.0",
"id": "PRD-DE-MUC-2025-DESK-F4A7B2",
"product_category": "furniture-office",
"name": "Standing Desk — Ergotron WorkFit",
"condition": "good",
"quantity": { "value": 12, "unit": "piece" },
"origin_city": "Munich",
"current_city": "Munich",
"available_from": "2026-03-15T08:00:00Z",
"manufacturer": "Ergotron",
"model": "WorkFit-S",
"manufacture_year": 2021,
"functional_status": "fully-functional",
"lifecycle_stage": "end-of-first-use",
"material_ids": [
"MAT-DE-MUC-2025-METAL-4EB84C",
"MAT-DE-MUC-2025-PLASTIC-96FE78"
]
}
4.5.5 Required Fields
schema_version: Schema version (0.2.0)id: Unique ProductDNA identifier (PRD- prefix)product_category: Standardized product categoryname: Product name (2-200 characters)condition: Physical condition (new, like-new, good, fair, poor, for-parts)quantity: Amount and unitorigin_city: Registering citycurrent_city: Current custodian cityavailable_from: When product becomes available
4.5.6 Product Categories
furniture/
furniture-office # Office furniture
furniture-residential # Residential furniture
furniture-industrial # Industrial furniture
building/
building-structural # Structural building components
building-fixture # Fixtures and fittings
building-hvac # HVAC equipment
building-electrical # Electrical installations
electronics/
electronics-computing # Computers and peripherals
electronics-mobile # Mobile devices
electronics-appliance # Household appliances
electronics-components # Electronic components
textiles/
textile-garment # Garments and clothing
textile-industrial # Industrial textiles
packaging/
packaging-reusable # Reusable packaging
vehicles/
vehicle-parts # Vehicle parts and components
equipment/
equipment-industrial # Industrial equipment
equipment-medical # Medical equipment
4.5.7 Offer/Match/Transfer with Products
The Offer, Match, and Transfer schemas accept either material_id or product_id. At least one MUST be present. This allows the same lifecycle flow (Offer → Match → Transfer) to work for both materials and products.
{
"@type": "Offer",
"product_id": "PRD-DE-MUC-2025-DESK-F4A7B2",
"from_city": "Munich",
"to_city": "Berlin",
...
}
5. LoopCoin Specification
5.1 Currency Properties
Each node's LoopCoin configuration:
{
"@context": "https://local-loop-io.github.io/projects/loop-protocol/contexts/loop-v0.1.1.jsonld",
"@type": "LoopCoinConfig",
"issuer": "munich.loop",
"currency_code": "LC-MUC",
"backed_by": "EUR",
"exchange_rate": 1.0,
"local_bonus": 0.05,
"expiry_months": 6,
"decay_rate": 0.05,
"max_issuance": 1000000,
"current_supply": 450000,
"reserve_ratio": 1.0
}
5.2 Transaction Format
{
"@context": "https://local-loop-io.github.io/projects/loop-protocol/contexts/loop-v0.1.1.jsonld",
"@type": "LoopCoinTransfer",
"id": "550e8400-e29b-41d4-a716-446655440000",
"from": "user:maria@munich.loop",
"to": "business:brewery@munich.loop",
"amount": 50,
"currency": "LC-MUC",
"material_ref": "MAT-DE-MUC-2025-FOOD-B847F3",
"timestamp": "2025-05-27T14:30:00Z",
"memo": "Payment for spent grain",
"signature": "..."
}
5.3 Inter-Node Settlement
When LoopCoins cross node boundaries:
{
"@context": "https://local-loop-io.github.io/projects/loop-protocol/contexts/loop-v0.1.1.jsonld",
"@type": "InterNodeSettlement",
"from_node": "munich.loop",
"to_node": "berlin.loop",
"transfers": [
{
"from": "business:brewery@munich.loop",
"to": "business:biogas@berlin.loop",
"amount": 65,
"from_currency": "LC-MUC",
"to_currency": "LC-BER",
"exchange_rate": 1.0,
"fees": {
"export_penalty": 26,
"import_penalty": 0,
"distance_cost": 12
}
}
],
"settlement_method": "clearing",
"settlement_period": "daily"
}
6. LoopSignal Specification
6.1 Signal Configuration
Community preferences for material categories:
{
"@context": "https://local-loop-io.github.io/projects/loop-protocol/contexts/loop-v0.1.1.jsonld",
"@type": "LoopSignalConfig",
"node": "munich.loop",
"signals": {
"plastic-pet": 0.30,
"plastic-hdpe": 0.25,
"metal-aluminum": 0.15,
"organic-food": 0.40,
"glass-clear": 0.10,
"paper-clean": 0.05,
"ewaste-phones": 0.35,
"default": 0.05
},
"valid_from": "2025-06-01T00:00:00Z",
"valid_until": "2025-06-30T23:59:59Z",
"approved_by": {
"vote_id": "2025-05-vote",
"turnout": 0.35,
"approval": 0.68
}
}
6.2 Signal Constraints
- Values MUST be between 0.0 and 1.0 (0% to 100%)
- Changes MUST NOT exceed 0.10 (10%) per voting period
- Nodes MUST publish signals publicly
- Signals MUST apply equally to imports and exports
6.3 Voting Record
{
"@context": "https://local-loop-io.github.io/projects/loop-protocol/contexts/loop-v0.1.1.jsonld",
"@type": "LoopVote",
"node": "munich.loop",
"vote_id": "2025-05-plastic-increase",
"proposals": [
{
"category": "plastic-pet",
"current_value": 0.20,
"proposed_value": 0.30,
"rationale": "Increase local plastic recycling"
}
],
"voting_period": {
"start": "2025-05-01T00:00:00Z",
"end": "2025-05-07T23:59:59Z"
},
"results": {
"total_eligible": 150000,
"total_voted": 52500,
"votes_for": 35700,
"votes_against": 16800,
"status": "passed"
}
}
7. LoopCost Calculation
7.1 Formula
The LoopCost for any material transaction:
LoopCost = BasePrice + ExportPenalty + ImportPenalty + DistanceCost
Where:
BasePrice: Offered price in LoopCoinsExportPenalty: BasePrice × OriginSignal (if leaving origin)ImportPenalty: BasePrice × DestinationSignal (if entering destination)DistanceCost: Distance_km × 0.02 LC/km
7.2 Calculation Rules
- Local transactions (same node): Only BasePrice applies
- Export penalty: Applied to seller's community fund
- Import penalty: Applied to buyer's community fund
- Distance cost: Split between nodes or transport provider
7.3 Reference Implementation
function calculateLoopCost(offer) {
const { basePrice, origin, destination, materialType, distance } = offer;
let loopCost = basePrice;
let exportPenalty = 0;
let importPenalty = 0;
let distanceCost = 0;
// Export penalty if material leaves origin
if (origin.node !== destination.node) {
const exportSignal = origin.getSignal(materialType);
exportPenalty = basePrice * exportSignal;
loopCost += exportPenalty;
}
// Import penalty if material enters destination
if (destination.node !== origin.node) {
const importSignal = destination.getSignal(materialType);
importPenalty = basePrice * importSignal;
loopCost += importPenalty;
}
// Distance cost (simplified)
if (distance > 0) {
distanceCost = distance * 0.02;
loopCost += distanceCost;
}
return {
total: loopCost,
breakdown: {
base: basePrice,
export: exportPenalty,
import: importPenalty,
distance: distanceCost
}
};
}
7.4 Settlement Distribution
For cross-node transactions:
Total Payment = LoopCost
├── Seller receives: BasePrice - ExportPenalty
├── Origin community fund: ExportPenalty
├── Destination community fund: ImportPenalty
└── Transport/Network: DistanceCost
8. API Endpoints
8.1 Required Endpoints
All LOOP nodes MUST implement these RESTful endpoints.
The repository openapi.json is the reference contract for the protocol endpoints in this section.
Lab-only extensions documented below are intentionally excluded from that artifact.
Material Management
POST /api/v1/material
POST /api/v1/material
Content-Type: application/ld+json
Authorization: Bearer {token}
{
"@context": "https://local-loop-io.github.io/projects/loop-protocol/contexts/loop-v0.1.1.jsonld",
"@type": "MaterialDNA",
"id": "MAT-DE-MUC-2025-PLASTIC-B847F3",
"category": "plastic-pet",
"quantity": {"value": 1000, "unit": "kg"},
...
}
Response: 201 Created
{
"@context": "https://local-loop-io.github.io/projects/loop-protocol/contexts/loop-v0.1.1.jsonld",
"@type": "MaterialDNA",
"id": "MAT-DE-MUC-2025-PLASTIC-B847F3",
"status": "registered",
...
}
GET /api/v1/material/{id}
GET /api/v1/material/MAT-DE-MUC-2025-PLASTIC-B847F3
Response: 200 OK
{
"@context": "https://local-loop-io.github.io/projects/loop-protocol/contexts/loop-v0.1.1.jsonld",
"@type": "MaterialDNA",
"id": "MAT-DE-MUC-2025-PLASTIC-B847F3",
...
}
POST /api/v1/material/search
POST /api/v1/material/search
Content-Type: application/ld+json
{
"category": "plastic-*",
"radius_km": 100,
"min_quantity": 500,
"max_loop_cost": 150
}
Response: 200 OK
{
"results": [...],
"total": 15,
"next": "/api/v1/material/search?page=2"
}
Product Management
ProductDNA is part of the v0.2.0 baseline. Nodes implementing the baseline MUST expose ProductDNA using the same JSON-LD and versioning rules as MaterialDNA.
POST /api/v1/product
POST /api/v1/product
Content-Type: application/ld+json
Authorization: Bearer {token}
{
"@context": "https://local-loop-io.github.io/projects/loop-protocol/contexts/loop-v0.2.0.jsonld",
"@type": "ProductDNA",
"schema_version": "0.2.0",
"id": "DE-MUC-2026-FURNITURE-CHAIR-001",
"product_category": "office-furniture",
"condition": "used-good",
...
}
Response: 201 Created
{
"@context": "https://local-loop-io.github.io/projects/loop-protocol/contexts/loop-v0.2.0.jsonld",
"@type": "ProductDNA",
"schema_version": "0.2.0",
"id": "DE-MUC-2026-FURNITURE-CHAIR-001",
"status": "registered",
...
}
GET /api/v1/product/{id}
GET /api/v1/product/DE-MUC-2026-FURNITURE-CHAIR-001
Response: 200 OK
{
"@context": "https://local-loop-io.github.io/projects/loop-protocol/contexts/loop-v0.2.0.jsonld",
"@type": "ProductDNA",
"schema_version": "0.2.0",
"id": "DE-MUC-2026-FURNITURE-CHAIR-001",
...
}
Material Management (Lab Demo Extensions)
The following endpoint is optional and used by the localLOOP lab demo only. It is not required for protocol compliance.
POST /api/v1/material-status
POST /api/v1/material-status
Content-Type: application/ld+json
X-API-Key: {api-key}
{
"@context": "https://local-loop-io.github.io/projects/loop-protocol/contexts/loop-v0.1.1.jsonld",
"@type": "MaterialStatusUpdate",
"schema_version": "0.1.1",
"id": "3c9a6a0b-8c1a-4d3f-9c2c-3c1c2f9d5c2a",
"material_id": "MAT-DE-MUC-2025-PLASTIC-B847F3",
"status": "reserved",
"updated_at": "2025-06-03T09:15:00Z",
"reason": "Reserved by city exchange",
"notes": "Holding until pickup is confirmed",
"source_node": "lab-hub.loop",
"metadata": { "ticket": "LAB-42" }
}
Response: 201 Created
{
"id": "3c9a6a0b-8c1a-4d3f-9c2c-3c1c2f9d5c2a",
"created_at": "2025-06-03T09:15:05Z"
}
Node Information
GET /api/v1/node/info
GET /api/v1/node/info
Response: 200 OK
{
"@context": "https://local-loop-io.github.io/projects/loop-protocol/contexts/loop-v0.1.1.jsonld",
"@type": "NodeInfo",
"id": "munich.loop",
"name": "Munich LOOP Node",
"version": "0.1.0",
"location": {"lat": 48.1351, "lon": 11.5820},
"capabilities": ["material-registry", "loopcoin", "loopsignal"],
"endpoint": "https://munich.loop/api/v1",
"statistics": {
"materials_active": 1247,
"transactions_daily": 89,
"loopcoin_supply": 450000
}
}
GET /api/v1/signals
GET /api/v1/signals
Response: 200 OK
{
"@context": "https://local-loop-io.github.io/projects/loop-protocol/contexts/loop-v0.1.1.jsonld",
"@type": "LoopSignalConfig",
"node": "munich.loop",
"signals": {
"plastic-pet": 0.30,
...
},
"valid_from": "2025-06-01T00:00:00Z",
"valid_until": "2025-06-30T23:59:59Z"
}
Transactions
POST /api/v1/transaction
POST /api/v1/transaction
Content-Type: application/ld+json
Authorization: Bearer {token}
{
"@context": "https://local-loop-io.github.io/projects/loop-protocol/contexts/loop-v0.1.1.jsonld",
"@type": "MaterialTransaction",
"id": "TXN-2025-05-27-001",
"material": "MAT-DE-MUC-2025-PLASTIC-B847F3",
"seller": "munich.loop",
"buyer": "berlin.loop",
"offer": {
"base_price": 120,
"loop_cost": 156
},
"timestamp": "2025-05-27T16:00:00Z"
}
Response: 201 Created
{
"@context": "https://local-loop-io.github.io/projects/loop-protocol/contexts/loop-v0.1.1.jsonld",
"@type": "TransactionStatus",
"transaction_id": "TXN-2025-05-27-001",
"status": "pending",
"updated_at": "2025-05-27T16:00:00Z",
"settlement_url": "/api/v1/transaction/TXN-2025-05-27-001"
}
8.2 Federation Endpoints
For node-to-node communication:
POST /api/v1/federate/announce
POST /api/v1/federate/announce
X-Node-Signature: {signature}
{
"@context": "https://local-loop-io.github.io/projects/loop-protocol/contexts/loop-v0.1.1.jsonld",
"@type": "MaterialAnnouncement",
"material": "MAT-DE-MUC-2025-PLASTIC-B847F3",
"origin": "munich.loop",
"available": true
}
POST /api/v1/federate/offer
POST /api/v1/federate/offer
X-Node-Signature: {signature}
{
"@context": "https://local-loop-io.github.io/projects/loop-protocol/contexts/loop-v0.1.1.jsonld",
"@type": "MaterialOffer",
"material": "MAT-DE-MUC-2025-PLASTIC-B847F3",
"from": "berlin.loop",
"base_price": 120,
"loop_cost": 156,
"valid_until": "2025-05-27T18:00:00Z"
}
8.3 Error Responses
Standard error format:
{
"error": {
"code": "MATERIAL_NOT_FOUND",
"message": "Material with ID MAT-DE-MUC-2025-PLASTIC-B847F3 not found",
"details": {
"searched_id": "MAT-DE-MUC-2025-PLASTIC-B847F3",
"timestamp": "2025-05-27T15:30:00Z"
}
}
}
Error codes:
INVALID_REQUEST: Malformed requestUNAUTHORIZED: Missing or invalid authenticationFORBIDDEN: Insufficient permissionsNOT_FOUND: Resource not foundCONFLICT: Resource conflictINTERNAL_ERROR: Server error
9. Federation Protocol
9.1 Node Discovery
Nodes maintain a registry of peers:
{
"@context": "https://local-loop-io.github.io/projects/loop-protocol/contexts/loop-v0.1.1.jsonld",
"@type": "NodeRegistry",
"version": "2025-05-27",
"nodes": [
{
"id": "munich.loop",
"endpoint": "https://munich.loop/api/v1",
"public_key": "-----BEGIN PUBLIC KEY-----...",
"capabilities": ["interop-v0.1.1", "loopcoin", "loopsignal"],
"location": {"lat": 48.1351, "lon": 11.5820},
"status": "active",
"last_seen": "2025-05-27T15:00:00Z"
}
]
}
9.2 Node Authentication
Node-to-node requests MUST include:
X-Node-ID: Requesting node identifierX-Node-Signature: Request signatureX-Timestamp: Request timestamp (±5 minutes tolerance)
9.3 Message Propagation
Material announcements follow controlled flooding:
- Node announces to direct peers
- Peers forward to their peers (TTL=3)
- Duplicate detection prevents loops
- Geographic radius limits propagation
9.4 Network Topology
Recommended peering strategy:
- 3-5 nearby nodes (< 200km)
- 2-3 regional nodes (200-1000km)
- 1-2 distant nodes (> 1000km)
10. Security Considerations
10.1 Transport Security
- All connections MUST use TLS 1.3 or higher
- Nodes MUST validate certificates
- Perfect Forward Secrecy REQUIRED
10.2 Authentication
- Users authenticate via OAuth 2.0 / OIDC
- Nodes authenticate via mutual TLS or signed requests
- API tokens MUST expire (recommended: 1 hour)
10.3 Data Privacy
- Personal data MUST NOT be included in MaterialDNA
- Transaction details are public, user identities are not
- Nodes MUST comply with local privacy laws (GDPR, etc.)
10.4 Rate Limiting
Recommended limits:
- User requests: 100/minute
- Node requests: 1000/minute
- Search queries: 10/minute
10.5 Audit Trail
Nodes MUST maintain immutable logs of:
- Material registrations
- Transaction settlements
- Signal changes
- Node interactions
11. Implementation Guidance
11.1 Minimum Viable Node
Required components:
- HTTPS server with valid certificate
- JSON-LD parser and validator
- Database for material registry
- Basic routing calculator
- Federation client
11.2 Technology Recommendations
- Languages: JavaScript/Node.js, Python, Go, Rust
- Databases: PostgreSQL, MongoDB, SQLite (small nodes)
- Message Queue: Redis, RabbitMQ (optional)
- Caching: Redis, Memcached (recommended)
11.3 Scaling Considerations
- Material registry: Index by category, location, availability
- Federation: Implement connection pooling
- Search: Consider Elasticsearch for large nodes
- Archival: Move expired materials to cold storage
11.4 Testing
Test suite MUST cover:
- Protocol compliance
- LoopCost calculations
- Federation connectivity
- Error handling
- Performance benchmarks
12. Examples
12.1 Complete Flow Example
Step 1: Munich registers spent grain
POST munich.loop/api/v1/material
{
"@context": "https://local-loop-io.github.io/projects/loop-protocol/contexts/loop-v0.1.1.jsonld",
"@type": "MaterialDNA",
"id": "MAT-DE-MUC-2025-FOOD-B847F3",
"category": "organic-food",
"quantity": {"value": 500, "unit": "kg"},
"quality": 0.90,
"location": {
"lat": 48.1372,
"lon": 11.5755,
"address": "Augustiner Brewery"
},
"available_from": "2025-05-27T08:00:00Z",
"expires": "2025-05-30T08:00:00Z"
}
Response:
{
"@context": "https://local-loop-io.github.io/projects/loop-protocol/contexts/loop-v0.1.1.jsonld",
"@type": "MaterialDNA",
"id": "MAT-DE-MUC-2025-FOOD-B847F3",
"status": "registered"
}
Step 2: Munich announces to network
POST vienna.loop/api/v1/federate/announce
{
"@context": "https://local-loop-io.github.io/projects/loop-protocol/contexts/loop-v0.1.1.jsonld",
"@type": "MaterialAnnouncement",
"material": "MAT-DE-MUC-2025-FOOD-B847F3",
"origin": "munich.loop",
"category": "organic-food",
"quantity": 500,
"available": true
}
Step 3: Vienna calculates LoopCost
Base offer: 60 LC
Munich export signal (40%): +24 LC
Vienna import signal (20%): +12 LC
Distance (400km × 0.02): +8 LC
Total LoopCost: 104 LC
Step 4: Vienna submits offer
POST munich.loop/api/v1/federate/offer
{
"@context": "https://local-loop-io.github.io/projects/loop-protocol/contexts/loop-v0.1.1.jsonld",
"@type": "MaterialOffer",
"material": "MAT-DE-MUC-2025-FOOD-B847F3",
"from": "vienna.loop",
"base_price": 60,
"loop_cost": 104,
"valid_until": "2025-05-27T18:00:00Z"
}
Step 5: Munich selects local buyer
{
"offers": [
{"from": "munich-farm", "loop_cost": 50},
{"from": "vienna.loop", "loop_cost": 104},
{"from": "berlin.loop", "loop_cost": 103}
],
"selected": "munich-farm",
"reason": "lowest_loop_cost"
}
12.2 Signal Voting Example
{
"@context": "https://local-loop-io.github.io/projects/loop-protocol/contexts/loop-v0.1.1.jsonld",
"@type": "SignalProposal",
"node": "munich.loop",
"changes": [
{
"category": "plastic-pet",
"current": 0.20,
"proposed": 0.30,
"reason": "Increase local plastic recycling"
}
],
"voting_opens": "2025-06-01T00:00:00Z",
"voting_closes": "2025-06-07T23:59:59Z"
}
{
"@context": "https://local-loop-io.github.io/projects/loop-protocol/contexts/loop-v0.1.1.jsonld",
"@type": "LoopVote",
"node": "munich.loop",
"vote_id": "2025-06-plastic-increase",
"proposals": [
{
"category": "plastic-pet",
"current_value": 0.20,
"proposed_value": 0.30,
"rationale": "Increase local plastic recycling"
}
],
"voting_period": {
"start": "2025-06-01T00:00:00Z",
"end": "2025-06-07T23:59:59Z"
},
"results": {
"total_eligible": 150000,
"total_voted": 52500,
"votes_for": 35700,
"votes_against": 16800,
"status": "passed"
}
}
13. Future Considerations
13.1 v0.2.0 Summary
v0.2.0 delivered the following (see Appendix B for full changelog):
- ProductDNA schema — product-level DPP entity referencing MaterialDNA composition
- Offer/Match/Transfer schemas accept
product_idas alternative tomaterial_id - Comprehensive DPP extension fields (ESPR, UNTP, Battery Passport, PPWR, NKWS aligned)
- Schema version consolidation (all schemas unified under v0.2.0)
- Complete JSON-LD context with all type and term mappings
- Conformity claims model (UNTP-aligned)
- EPCIS event references and W3C VC pointers in traceability blocks
- Schema versioning policy (RFC-0003)
13.2 Future Features
- Smart contract integration for automated settlement (see RFC-0004)
- Multi-material bundles for efficient trading
- Reputation system for reliable traders
- Advanced routing with machine learning
- Mobile node implementations
13.3 Research Areas
- Zero-knowledge proofs for private transactions
- Decentralized identity for users
- Carbon credit integration
- IoT sensor integration
- Cross-chain interoperability
13.4 Standardization
Goal: Submit to standards body (W3C, IETF) after v1.0
14. References
-
Carlsson, R., Nevzorova, T. (2025). "Internet of Materials – A concept for circular material traceability". Cleaner Engineering and Technology, 25, 100911. https://doi.org/10.1016/j.clet.2025.100911
-
W3C. (2018). "ActivityPub". W3C Recommendation. https://www.w3.org/TR/activitypub/
-
W3C. (2020). "JSON-LD 1.1". W3C Recommendation. https://www.w3.org/TR/json-ld11/
-
IETF. (2014). "RFC 7231: Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content". https://tools.ietf.org/html/rfc7231
-
IETF. (1997). "RFC 2119: Key words for use in RFCs to Indicate Requirement Levels". https://www.ietf.org/rfc/rfc2119.txt
-
Bernstein, D. J. (2006). "Curve25519: new Diffie-Hellman speed records". Public Key Cryptography - PKC 2006. pp. 207–228.
-
European Parliament and Council. (2024). "Regulation (EU) 2024/1781 on ecodesign requirements for sustainable products (ESPR)". https://eur-lex.europa.eu/eli/reg/2024/1781/oj/eng
-
UN/CEFACT. (2024). "United Nations Transparency Protocol (UNTP) — Digital Product Passport". https://uncefact.github.io/spec-untp/
-
German Federal Government. (2024). "National Circular Economy Strategy (Nationale Kreislaufwirtschaftsstrategie — NKWS)". https://www.bundesumweltministerium.de/en/topics/circular-economy/circular-economy-strategy
Appendix A: JSON-LD Context
The canonical JSON-LD context for v0.2.0 is published at:
https://local-loop-io.github.io/projects/loop-protocol/contexts/loop-v0.2.0.jsonld
The v0.1.1 context remains available at:
https://local-loop-io.github.io/projects/loop-protocol/contexts/loop-v0.1.1.jsonld
Implementations MUST treat the published context files as the source of truth. This appendix is intentionally brief to avoid drift between the specification text and the published context files.
Key properties of the v0.2.0 context:
- It is a superset of the v0.1.1 context (all v0.1.1 mappings are preserved)
- It adds type mappings for all 16+ entity types across all 10 schemas
- It adds term mappings for all DPP extension fields (passport, classification, traceability, conformity claims)
- It adds term mappings for v1-origin schema fields (settlement, voting, signals, transactions)
- It sets
@vocabto the LOOP terms namespace so additive fields expand predictably - It keeps date-time fields typed for interoperable processing
Appendix B: Change Log
Version 0.2.0 (2026-03-08)
- Unified all 10 schemas under v0.2.0 (eliminated v0.1.1/v1 split)
- Added comprehensive DPP extension fields (ESPR, UNTP, Battery Passport, PPWR, NKWS aligned)
- Added conformity claims model
- Added EPCIS event references and W3C VC pointers
- Completed JSON-LD context with all type and term mappings
- Fixed factual errors (Green Claims Directive withdrawal, BMUV URL)
- Clarified dual license (MIT for code, CC BY-SA 4.0 for prose)
- Established schema versioning policy (RFC-0003)
- Backend API paths aligned to
/api/v1/ - Added ProductDNA schema (product-level DPP entity, ESPR Art. 9-10 aligned)
- Offer/Match/Transfer schemas now accept
product_idas alternative tomaterial_id(anyOf) - Added product category enum (17 categories across furniture, building, electronics, textile, packaging, vehicle, equipment)
- Added ProductDNA term mappings to JSON-LD context
Version 0.1.1 (2025-12-20)
- Minimal interop flow definition (MaterialDNA → Offer → Match → Transfer)
- JSON schemas for Offer, Match, Transfer, MaterialStatusUpdate, NodeHandshake
- Lab demo baseline with data minimization rules
Version 0.1.0 (2025-05-27)
- Initial specification release
- Core protocol definition
- Basic federation support
- Reference calculations
End of Specification
This specification is released under Creative Commons BY-SA 4.0. Code and schemas are released under the MIT license. Contributions welcome at https://github.com/local-loop-io/loop-protocol