Skip to content

Latest commit

 

History

History
1391 lines (1080 loc) · 42 KB

File metadata and controls

1391 lines (1080 loc) · 42 KB

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

  1. Introduction
  2. Terminology
  3. Protocol Overview
  4. MaterialDNA Specification
  5. LoopCoin Specification
  6. LoopSignal Specification
  7. LoopCost Calculation
  8. API Endpoints
  9. Federation Protocol
  10. Security Considerations
  11. Implementation Guidance
  12. Examples
  13. Future Considerations
  14. 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:

  1. Enable any city to participate in global material exchange
  2. Preserve local economic sovereignty
  3. Optimize material flows through market mechanisms
  4. Incorporate democratic community preferences
  5. Create transparent, auditable transactions
  6. 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.

flowchart LR
  Munich[Munich Node]
  Berlin[Berlin Node]
  Vienna[Vienna Node]
  Munich <-->|HTTPS| Berlin
  Munich --- Vienna
  Berlin --- Vienna
Loading

3.2 Core Components

Each LOOP node MUST implement:

  1. Material Registry: Tracks MaterialDNA within node jurisdiction
  2. Product Registry: Tracks ProductDNA (DPP-compatible product identifiers) within node jurisdiction
  3. Currency Engine: Manages LoopCoin issuance and transfers
  4. Signal Governor: Handles democratic voting on preferences
  5. Routing Calculator: Computes optimal destinations using LoopCost
  6. Settlement Handler: Confirms and records transactions

3.3 Communication Flow

Standard material exchange flow:

  1. Registration: Material registered with unique MaterialDNA
  2. Announcement: Availability broadcast to federated nodes
  3. Discovery: Interested nodes discover available materials
  4. Calculation: Each node calculates their LoopCost
  5. Offer: Nodes submit offers to material owner
  6. Selection: Optimal match determined by lowest/highest LoopCost
  7. Settlement: Transaction executed and confirmed
  8. 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

  1. MaterialDNA is registered by a node.
  2. Offer is published for that material.
  3. Match is accepted between two nodes.
  4. 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 material
  • COUNTRY: ISO 3166-1 alpha-2 code
  • CITY: Three-letter city code (locally defined)
  • YEAR: Four-digit year of registration
  • CATEGORY: Material category code
  • UNIQUE: 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 identifier
  • category: Standardized category code
  • quantity: Amount and unit
  • origin_city: Registering city
  • current_city: Current custodian city
  • available_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 product
  • COUNTRY: ISO 3166-1 alpha-2 code
  • CITY: Three-letter city code
  • YEAR: Four-digit year of registration
  • CATEGORY: Product category keyword
  • UNIQUE: 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 category
  • name: Product name (2-200 characters)
  • condition: Physical condition (new, like-new, good, fair, poor, for-parts)
  • quantity: Amount and unit
  • origin_city: Registering city
  • current_city: Current custodian city
  • available_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 LoopCoins
  • ExportPenalty: BasePrice × OriginSignal (if leaving origin)
  • ImportPenalty: BasePrice × DestinationSignal (if entering destination)
  • DistanceCost: Distance_km × 0.02 LC/km

7.2 Calculation Rules

  1. Local transactions (same node): Only BasePrice applies
  2. Export penalty: Applied to seller's community fund
  3. Import penalty: Applied to buyer's community fund
  4. 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 request
  • UNAUTHORIZED: Missing or invalid authentication
  • FORBIDDEN: Insufficient permissions
  • NOT_FOUND: Resource not found
  • CONFLICT: Resource conflict
  • INTERNAL_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:

  1. X-Node-ID: Requesting node identifier
  2. X-Node-Signature: Request signature
  3. X-Timestamp: Request timestamp (±5 minutes tolerance)

9.3 Message Propagation

Material announcements follow controlled flooding:

  1. Node announces to direct peers
  2. Peers forward to their peers (TTL=3)
  3. Duplicate detection prevents loops
  4. 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:

  1. HTTPS server with valid certificate
  2. JSON-LD parser and validator
  3. Database for material registry
  4. Basic routing calculator
  5. 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_id as alternative to material_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

  1. 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

  2. W3C. (2018). "ActivityPub". W3C Recommendation. https://www.w3.org/TR/activitypub/

  3. W3C. (2020). "JSON-LD 1.1". W3C Recommendation. https://www.w3.org/TR/json-ld11/

  4. IETF. (2014). "RFC 7231: Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content". https://tools.ietf.org/html/rfc7231

  5. IETF. (1997). "RFC 2119: Key words for use in RFCs to Indicate Requirement Levels". https://www.ietf.org/rfc/rfc2119.txt

  6. Bernstein, D. J. (2006). "Curve25519: new Diffie-Hellman speed records". Public Key Cryptography - PKC 2006. pp. 207–228.

  7. 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

  8. UN/CEFACT. (2024). "United Nations Transparency Protocol (UNTP) — Digital Product Passport". https://uncefact.github.io/spec-untp/

  9. 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 @vocab to 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_id as alternative to material_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