Consuming Register Data

When your application depends on a FERIN register, you need patterns for reliable access, version management, and change notification.

Access Patterns

Direct API Access

Query the register directly for each request. Simple but creates runtime dependency.

Pros:
  • Always up-to-date
  • Simple implementation
  • No local storage needed
Cons:
  • Runtime dependency on register availability
  • Network latency on each query
  • Rate limiting considerations

Local Cache

Cache register data locally, refresh on schedule or notification.

Pros:
  • No runtime dependency
  • Fast local queries
  • Works offline
Cons:
  • Staleness between refreshes
  • Cache invalidation complexity
  • Local storage requirements

Event-Driven Sync

Subscribe to register change events, maintain local synchronized copy.

Pros:
  • Near real-time updates
  • Efficient - only transfer changes
  • No polling overhead
Cons:
  • Requires register to support webhooks/events
  • Event ordering considerations
  • Recovery from missed events

Schema Version Negotiation

When consuming data, specify which schema version you need:

# Request data at specific schema version
GET /items/meter?schemaVersion=1.0

# Response includes schema version in metadata
{
  "id": "urn:iso:std:iso:80000:1:meter",
  "schemaVersion": "1.0",
  "content": {
    "name": "meter",
    "symbol": "m",
    "description": "SI unit of length"
    # No category field - not in v1
  },
  "status": "valid"
}

# Request at newer version
GET /items/meter?schemaVersion=2.0

{
  "id": "urn:iso:std:iso:80000:1:meter",
  "schemaVersion": "2.0",
  "content": {
    "name": "meter",
    "symbol": "m",
    "description": "SI unit of length",
    "category": "SI"  # New in v2
  },
  "status": "valid"
}

Temporal Queries

Query the register state at a specific point in time:

# What was the state on a specific date?
GET /items?asOf=2023-06-15T00:00:00Z

# What items were valid at that time?
GET /items?asOf=2023-06-15T00:00:00Z&status=valid

# Historical version of specific item
GET /items/meter/history?at=2020-01-01T00:00:00Z

Publishing a Register

When you publish a FERIN register for others to consume, provide clear APIs, documentation, and change notification mechanisms.

API Design Principles

Version Your Endpoints

Allow consumers to request specific schema versions. Don't force upgrades on your schedule.

# Version in query parameter
GET /items?schemaVersion=2.0

# Version in header
GET /items
Accept: application/json; version=2.0

# Version in URL path (if you prefer)
GET /v2/items

Provide Change Feeds

Enable consumers to discover changes efficiently without full sync.

# Get changes since timestamp
GET /changes?since=2024-01-01T00:00:00Z

Response:
{
  "changes": [
    {
      "itemId": "urn:example:item:123",
      "action": "modified",
      "timestamp": "2024-01-15T10:00:00Z",
      "schemaVersion": "2.0"
    }
  ],
  "next": "/changes?since=2024-01-15T10:00:00Z"
}

Support Webhooks

Allow consumers to register for push notifications on changes.

# Consumer registers webhook
POST /webhooks
{
  "url": "https://consumer.example.com/webhook",
  "events": ["item.created", "item.modified", "item.invalidated"],
  "filters": {
    "itemClass": "Unit"
  }
}

# Register sends notification
POST https://consumer.example.com/webhook
{
  "event": "item.modified",
  "itemId": "urn:example:item:123",
  "timestamp": "2024-01-15T10:00:00Z",
  "signature": "sha256=..."  # Verify authenticity
}

Document Commitments

Make your commitments explicit so consumers know what to expect.

# Register metadata endpoint
GET /register

{
  "id": "urn:example:units-register",
  "title": "Units of Measure Register",
  "commitments": {
    "access": "public",
    "persistence": "permanent",
    "transparency": "full",
    "availability": "99.9%",
    "retention": "permanent",
    "deprecationNotice": "6 months minimum"
  },
  "schemaVersions": ["1.0", "2.0"],
  "currentSchemaVersion": "2.0"
}

Cross-Register Dependencies

When your register references items in other registers, you have dependencies that need careful management.

Dependency Patterns

Reference by Identifier

Store the external item's identifier. Resolve at runtime when needed.

{
  "id": "urn:example:my-item",
  "references": {
    "unit": "urn:iso:std:iso:80000:1:meter"
  }
}

# Resolve external reference
GET https://iso.org/registers/80000/items/meter

Cached Reference

Cache key data from external item, but track source for updates.

{
  "id": "urn:example:my-item",
  "unit": {
    "source": "urn:iso:std:iso:80000:1:meter",
    "cachedAt": "2024-01-15T00:00:00Z",
    "cachedData": {
      "symbol": "m",
      "name": "meter"
    }
  }
}

Versioned Reference

Reference a specific version of the external item.

{
  "id": "urn:example:my-item",
  "references": {
    "unit": {
      "id": "urn:iso:std:iso:80000:1:meter",
      "version": "2.0",
      "asOf": "2024-01-15T00:00:00Z"
    }
  }
}

Managing Dependencies

Track Dependencies

Maintain a registry of all external references. Know which items depend on which external sources.

Subscribe to Changes

If the external register supports notifications, subscribe to changes affecting your dependencies.

Plan for Unavailability

Define what happens when an external register is unavailable. Cache enough data to continue operating.

Handle Breaking Changes

When external items are invalidated or superseded, assess impact and update references as needed.

Error Handling

ScenarioConsumer Action
Register unavailableUse cached data, retry with exponential backoff, alert if prolonged
Item not foundCheck if superseded, query history, handle gracefully
Schema version unsupportedRequest older version, or adapt to newer version
Rate limitedRespect headers, implement backoff, consider caching
External reference brokenUse cached data, flag for review, notify register owner

Related Topics