API Specification
All HTTP endpoints for terms retrieval, verification, acceptance, and dispute resolution.
The ALC API provides HTTP/JSON access to all legal context operations. It bridges the agent world (HTTP/JSON) to the on-chain world (smart contracts, resolvers) without requiring agents to have web3 libraries, RPC providers, or blockchain knowledge.
All endpoints MUST be served over HTTPS. All request and response bodies MUST use application/json content type unless otherwise specified. All timestamps in response body fields use ISO 8601 format. Exception: The timestamp and expiry fields in POST /v1/records/{recordId}/accept are Unix epoch integers (uint256) to match EIP-712 signed data exactly.
Create Record
Creates a new on-chain record (IntegraRecord in the reference implementation). Used by vendors to register their terms (Tier 1/2) and by parties to register negotiated agreements (Tier 3).
POST /v1/recordsRequest:
{
"terms": {
"url": "https://example.com/terms/v1.html"
},
"resolvers": {
"documentLocation": true,
"contact": {
"legal": "[email protected]",
"technical": "[email protected]"
},
"disputeResolution": {
"method": "AAA Commercial Rules",
"jurisdiction": "New York, USA"
}
},
"chain": "tempo",
"acceptanceRequired": false
}| Field | Type | Required | Description |
|---|---|---|---|
terms.url | string | One of url/document | URL of the terms document. The API will fetch and snapshot it. |
terms.document | string | One of url/document | Base64-encoded terms document bytes for direct upload. |
resolvers | object | REQUIRED | Resolver configuration. At minimum documentLocation MUST be true. |
chain | string | OPTIONAL | Target chain for the on-chain record. |
acceptanceRequired | boolean | OPTIONAL | Whether counterparties must explicitly accept (Tier 2). Default: false. |
Response (201 Created):
{
"recordId": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
"contentHash": "0x7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069",
"chain": "tempo",
"chainId": 42431,
"transactionHash": "0x...",
"api": "https://api.integraledger.net/v1/records/0xabcdef1234567890...",
"status": "active"
}The response includes the api URL that the vendor SHOULD place in their legal-context.json discovery document.
Get Record
Retrieves record metadata for a given on-chain record.
GET /v1/records/{recordId}Response (200 OK):
{
"recordId": "0xabcdef...",
"contentHash": "0x7f83b165...",
"chain": "tempo",
"chainId": 42431,
"contractAddress": "0x1234...5678",
"effectiveDate": "2026-03-01T00:00:00Z",
"state": "active",
"resolvers": {
"documentLocation": "https://api.integraledger.net/v1/records/0xabcdef.../terms",
"contact": "https://api.integraledger.net/v1/records/0xabcdef.../contact",
"disputeResolution": "https://api.integraledger.net/v1/records/0xabcdef.../dispute"
},
"versions": [
{
"contentHash": "0x7f83b165...",
"effectiveDate": "2026-03-01T00:00:00Z",
"status": "current"
},
{
"contentHash": "0x3a4b5c6d...",
"effectiveDate": "2025-09-15T00:00:00Z",
"status": "superseded"
}
]
}Get Terms
Retrieves the actual terms document -- the exact bytes that were hashed to produce the contentHash.
GET /v1/records/{recordId}/terms| Parameter | Type | Required | Description |
|---|---|---|---|
version | query string | OPTIONAL | A specific contentHash to retrieve a historical version. |
The response body IS the terms document. The Content-Type header indicates the format (e.g., text/html, application/pdf, application/json).
Verification: Clients SHOULD verify by computing SHA-256(response body) and comparing to the contentHash.
Required response headers:
| Header | Description |
|---|---|
X-Integra-Hash | The contentHash of the returned document |
X-Integra-Record | The recordId on-chain |
X-Integra-Chain | The chain identifier |
Verify Hash
Verifies whether a given hash corresponds to a valid, on-chain-anchored terms record.
GET /v1/verify/{contentHash}Response (200 OK):
{
"verified": true,
"contentHash": "0x7f83b165...",
"recordId": "0xabcdef...",
"chain": "tempo",
"chainId": 42431,
"effectiveDate": "2026-03-01T00:00:00Z",
"status": "current",
"vendor": {
"domain": "example.com"
}
}Response (404 Not Found):
{
"verified": false,
"contentHash": "0x7f83b165...",
"error": "Hash not found in any registered IntegraRecord"
}Accept Terms
Records an explicit terms acceptance (Tier 2). The request body contains an EIP-712 signature over the content hash.
POST /v1/records/{recordId}/acceptRequest:
{
"contentHash": "0x7f83b165...",
"acceptor": "0x742d35Cc...",
"principal": "0x9f8e7d6c...",
"authorizationRef": "0xaabbccdd...",
"signature": "0x...",
"timestamp": 1710856200,
"expiry": 1742392200
}| Field | Type | Required | Description |
|---|---|---|---|
contentHash | string | REQUIRED | Hash of the terms being accepted. |
acceptor | string | REQUIRED | Ethereum address of the accepting party (agent or human). |
principal | string | OPTIONAL | Ethereum address of the human principal, if acceptor is an agent. |
authorizationRef | string | OPTIONAL | Reference to the authorization grant. |
signature | string | REQUIRED | EIP-712 signature over the TermsAcceptance typed data. |
timestamp | integer | REQUIRED | Unix epoch timestamp. MUST match the EIP-712 signed data. |
expiry | integer | OPTIONAL | Unix epoch timestamp after which acceptance is no longer valid. |
The timestamp and expiry fields are integers (Unix epoch seconds), not ISO 8601 strings. This ensures they match the uint256 values in the EIP-712 typed data exactly.
Response (201 Created):
{
"acceptanceId": "0x...",
"contentHash": "0x7f83b165...",
"acceptor": "0x742d35Cc...",
"status": "recorded",
"onChainRef": {
"chain": "tempo",
"transactionHash": "0x..."
}
}Get Contact Information
Retrieves structured contact information for the vendor.
GET /v1/records/{recordId}/contactResponse (200 OK):
{
"legal": {
"email": "[email protected]",
"name": "Example Corp Legal Department"
},
"technical": {
"email": "[email protected]",
"endpoint": "https://support.example.com/api"
},
"dispute": {
"email": "[email protected]",
"endpoint": "https://api.integraledger.net/v1/records/0xabcdef.../disputes",
"method": "AAA Commercial Arbitration Rules",
"jurisdiction": "New York, USA"
}
}Get Dispute Resolution Process
Retrieves the dispute resolution process for agreements under these terms.
GET /v1/records/{recordId}/disputeResponse (200 OK):
{
"method": "AAA Commercial Arbitration Rules",
"jurisdiction": "New York, USA",
"automated": {
"enabled": true,
"threshold": "1000.00",
"currency": "USD",
"description": "Disputes under $1,000 resolved automatically via pre-defined rules"
},
"escalation": {
"enabled": true,
"threshold": "1000.00",
"institution": "American Arbitration Association",
"rules": "Commercial Arbitration Rules",
"filing": "https://api.integraledger.net/v1/records/0xabcdef.../disputes"
},
"resolver": {
"chain": "tempo",
"address": "0x9876...5432",
"type": "ADRResolverV3"
}
}File Dispute
Initiates a dispute under the terms governing a specific transaction.
POST /v1/records/{recordId}/disputesRequest:
{
"claimant": "0x742d35Cc...",
"respondent": "0x9f8e7d6c...",
"transactionRef": {
"chain": "tempo",
"transactionHash": "0x...",
"contentHash": "0x7f83b165..."
},
"category": "non-delivery",
"description": "Service was not delivered within the SLA specified in the terms",
"evidenceHashes": ["0xaaaa...", "0xbbbb..."],
"requestedRelief": "refund"
}Response (201 Created):
{
"disputeId": "0x...",
"status": "filed",
"resolverAddress": "0x9876...5432",
"nextSteps": "Evidence submission period: 14 days",
"onChainRef": {
"chain": "tempo",
"transactionHash": "0x..."
}
}Error Responses
All error responses conform to RFC 9457 Problem Details format:
{
"type": "https://integraledger.net/problems/record-not-found",
"title": "Record Not Found",
"status": 404,
"detail": "No IntegraRecord found for the specified recordId",
"instance": "/v1/records/0xabcdef..."
}| HTTP Status | Type | Description |
|---|---|---|
| 400 | invalid-request | Request body fails schema validation |
| 401 | unauthorized | Missing or invalid authentication |
| 404 | record-not-found | IntegraRecord does not exist |
| 404 | hash-not-found | contentHash not recognized |
| 409 | already-accepted | Terms already accepted by this address |
| 422 | invalid-signature | EIP-712 signature verification failed |
| 422 | hash-mismatch | Provided contentHash does not match the record |
| 502 | chain-unavailable | On-chain verification temporarily unavailable |
Authentication
Endpoints that modify state (POST methods) MUST require authentication. Implementations SHOULD support:
- API key authentication via
Authorization: Bearer {key}header - EIP-712 signed request bodies (self-authenticating)
Endpoints that only read state (GET methods) SHOULD be publicly accessible to enable open verification.
Deployment Models
The API MAY be hosted in three configurations. All three MUST implement the same interface. Clients MUST NOT need to know which model is in use.
| Model | Description | Vendor Effort | Control |
|---|---|---|---|
| Hosted (e.g., Integra) | Vendor creates a record. A hosted ALC API fronts it. | Zero infrastructure | Provider operates the API |
| Self-hosted | Vendor runs the API, pointing at their own on-chain records. | Full infrastructure | Full vendor control |
| Third-party hosted | Consortium or platform runs the API for its members. | Depends on provider | Third-party operates the API |