Integration Patterns
Practical guidance for integrating with FERIN registers - whether you're consuming data from a register, publishing your own register, or building cross-register dependencies.
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.
- Always up-to-date
- Simple implementation
- No local storage needed
- Runtime dependency on register availability
- Network latency on each query
- Rate limiting considerations
Local Cache
Cache register data locally, refresh on schedule or notification.
- No runtime dependency
- Fast local queries
- Works offline
- Staleness between refreshes
- Cache invalidation complexity
- Local storage requirements
Event-Driven Sync
Subscribe to register change events, maintain local synchronized copy.
- Near real-time updates
- Efficient - only transfer changes
- No polling overhead
- 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:00ZPublishing 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/itemsProvide 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/meterCached 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
| Scenario | Consumer Action |
|---|---|
| Register unavailable | Use cached data, retry with exponential backoff, alert if prolonged |
| Item not found | Check if superseded, query history, handle gracefully |
| Schema version unsupported | Request older version, or adapt to newer version |
| Rate limited | Respect headers, implement backoff, consider caching |
| External reference broken | Use cached data, flag for review, notify register owner |