🔌 DAON API Reference
Complete REST API documentation for integrating DAON creator protection into any platform.
🚀 Base Information
API Endpoints
- Production:
https://api.daon.network/v1/ - Sandbox:
https://sandbox-api.daon.network/v1/ - Documentation:
https://api.daon.network/docs
Authentication
Authorization: Bearer your-api-key-here
Content-Type: application/json
Rate Limits
- Free Tier: 1,000 protections/month, 100 requests/minute
- Creator Tier: 10,000 protections/month, 500 requests/minute
- Platform Tier: 100,000 protections/month, 2,000 requests/minute
Provenance associations
A registration and a provenance chain are separate records. Nothing links them in the database — both derive from the same content, so anyone holding it computes both and checks both. These endpoints record what somebody asserted, which is a different thing from what is true.
POST /content/{contentHash}/association
Assert that a chain covers registered content. Requires authentication, because an assertion nobody can be held to is not worth recording.
{
"entity_id": "sha256:…", // the chain's genesis leaf hash
"head": "sha256:…", // its head at this moment
"author_key": "sha256:…", // optional; needed to detect a key change
"recovery_key": "sha256:…",
"proof": "0a1b2c…" // optional; hex of a verifier claim buffer
}
Associations are never exclusive. Any number of accounts may assert a chain for one content hash and none displaces another. A unique constraint would let whoever asserted first squat the hash, and the person best placed to do that is not the creator.
A key change waits for the owner of record:
| Asserter | Keys | Result |
|---|---|---|
| is the owner of record | any | current — asserting is attesting |
| anyone | unchanged | current — the chain simply grew |
| someone else | changed | pending, owner emailed, expires in 5 days |
| — (no owner of record) | changed | current, marked never attested |
Silence refuses. A pending assertion expires unanswered rather than being accepted, because if silence accepted, the winning move would be to assert against somebody on holiday and say nothing.
Supplying proof makes verified true, and it means less than it sounds like.
DAON runs the verifier — the same wasm32 build a skeptic runs in a browser — and
confirms the leaf proves into a witnessed head. It says nothing about who owns
anything: a thief’s rotation verifies perfectly, because the stolen key is the
recorded key. Which is why a verified assertion still waits for the owner.
GET /content/{contentHash}/associations
Every chain asserted for this content, oldest first. More than one is normal and DAON does not rank them — deciding between competing claims belongs to a forum with standing to decide.
POST /associations/{id}/attest · POST /associations/{id}/dispute
The owner of record resolves a pending association. Attesting makes it current; disputing records the denial, dated and attributed. The assertion stays on the record either way, because that it was made is a fact.
GET /associations/resolve/{token} · POST /associations/resolve/{token}
The same two answers, from the notification email, without signing in.
GET renders a page; only POST changes anything. Mail scanners and corporate
security proxies fetch every URL in a message, so a GET that resolved would have
those systems answering on the creator’s behalf. The token is single-use and dies
with the request’s five-day deadline.
📝 Core Endpoints
POST /protect
Register content with cryptographic protection.
Request:
POST /v1/protect
Authorization: Bearer api_key_here
Content-Type: application/json
{
"content": "Your creative work content here...",
"metadata": {
"title": "Work Title",
"author": "Creator Name",
"description": "Optional description",
"url": "https://example.com/work",
"type": "article|story|poem|code|research",
"tags": ["tag1", "tag2"],
"language": "en"
},
"license": "liberation_v1|cc_by_nc|cc_by_sa|all_rights",
"platform": "wordpress|ao3|medium|custom"
}
Response:
{
"success": true,
"data": {
"contentHash": "7f8b9c2d4a1e3f5a9b7d2c8e6f4a9b8c",
"verificationUrl": "https://verify.daon.network/7f8b9c2d4a1e3f5a",
"timestamp": "2024-03-15T14:32:17.123Z",
"blockHeight": 12345,
"license": "liberation_v1",
"protectionId": "prot_1234567890abcdef"
}
}
Error Response:
{
"success": false,
"error": {
"code": "CONTENT_TOO_LARGE",
"message": "Content exceeds 10MB limit",
"details": {
"maxSizeBytes": 10485760,
"actualSizeBytes": 15728640
}
}
}
GET /verify/{contentHash}
Verify content protection and get details.
Request:
GET /v1/verify/7f8b9c2d4a1e3f5a9b7d2c8e6f4a9b8c
Authorization: Bearer api_key_here
Response:
{
"success": true,
"data": {
"isValid": true,
"contentHash": "7f8b9c2d4a1e3f5a9b7d2c8e6f4a9b8c",
"protectionId": "prot_1234567890abcdef",
"timestamp": "2024-03-15T14:32:17.123Z",
"blockHeight": 12345,
"license": "liberation_v1",
"metadata": {
"title": "Work Title",
"author": "Creator Name",
"type": "article"
},
"verificationUrl": "https://verify.daon.network/7f8b9c2d4a1e3f5a",
"blockchainTx": "0x1234567890abcdef..."
}
}
POST /protect/bulk
Protect multiple works in a single request.
Request:
POST /v1/protect/bulk
Authorization: Bearer api_key_here
Content-Type: application/json
{
"works": [
{
"content": "First work content...",
"metadata": {
"title": "First Work",
"author": "Creator Name"
}
},
{
"content": "Second work content...",
"metadata": {
"title": "Second Work",
"author": "Creator Name"
}
}
],
"license": "liberation_v1",
"platform": "wordpress"
}
Response:
{
"success": true,
"data": {
"totalWorks": 2,
"protected": 2,
"failed": 0,
"results": [
{
"index": 0,
"status": "protected",
"contentHash": "7f8b9c2d4a1e3f5a...",
"verificationUrl": "https://verify.daon.network/...",
"protectionId": "prot_1234567890"
},
{
"index": 1,
"status": "protected",
"contentHash": "9a8b7c6d5e4f3a2b...",
"verificationUrl": "https://verify.daon.network/...",
"protectionId": "prot_0987654321"
}
]
}
}
API Key Authentication
Authorization: Bearer sk_live_1234567890abcdef
Getting API Keys
- Free Account: Sign up for free tier
- Paid Tiers: Upgrade account for higher limits
- Enterprise: Contact sales for custom limits
API Key Types
sk_live_... - Production API key
sk_test_... - Sandbox/testing API key
sk_readonly_... - Read-only verification key
⚠️ Error Codes
Common Error Codes
{
"INVALID_API_KEY": "Authentication failed",
"RATE_LIMIT_EXCEEDED": "Too many requests",
"CONTENT_TOO_LARGE": "Content exceeds 10MB limit",
"INVALID_LICENSE": "Unknown license type",
"NETWORK_ERROR": "Temporary service unavailability",
"VALIDATION_ERROR": "Invalid request format",
"INSUFFICIENT_CREDITS": "API limit exceeded"
}
Error Response Format
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid content format",
"details": {
"field": "content",
"issue": "Content cannot be empty"
},
"timestamp": "2024-03-15T14:32:17Z",
"requestId": "req_1234567890"
}
}
HTTP Status Codes
200- Success400- Bad Request (validation error)401- Unauthorized (invalid API key)403- Forbidden (insufficient permissions)429- Too Many Requests (rate limited)500- Internal Server Error503- Service Unavailable
📊 Rate Limiting
Rate Limit Headers
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1679155937
X-RateLimit-Type: requests
Handling Rate Limits
// Example error handling
if (response.status === 429) {
const resetTime = response.headers['X-RateLimit-Reset'];
const waitTime = (resetTime * 1000) - Date.now();
await new Promise(resolve => setTimeout(resolve, waitTime));
// Retry request
}
Best Practices
- Batch requests using
/protect/bulkendpoint - Implement exponential backoff for retries
- Cache verification results to reduce API calls
- Use webhooks for async processing
🔗 Webhooks
Webhook Events
protection.completed - Content protection finished
protection.failed - Protection attempt failed
verification.requested - Someone verified your content
blockchain.confirmed - Protection confirmed on blockchain
Webhook Payload
{
"event": "protection.completed",
"timestamp": "2024-03-15T14:32:17Z",
"data": {
"protectionId": "prot_1234567890",
"contentHash": "7f8b9c2d...",
"verificationUrl": "https://verify.daon.network/...",
"metadata": {
"title": "Work Title"
}
},
"signature": "sha256=1234567890abcdef..."
}
Webhook Verification
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return `sha256=${expectedSignature}` === signature;
}
🛠️ SDK Examples
Node.js/JavaScript
import { DAON } from 'daon-sdk';
const daon = new DAON('your-api-key');
// Protect content
const result = await daon.protect('My creative work', {
title: 'My Story',
author: 'Author Name'
}, 'liberation_v1');
console.log('Protected:', result.verificationUrl);
Python
import daon
daon.api_key = 'your-api-key'
# Protect content
result = daon.protect(
content='My creative work',
metadata={'title': 'My Story', 'author': 'Author Name'},
license='liberation_v1'
)
print(f"Protected: {result.verification_url}")
Ruby
require 'daon'
Daon.api_key = 'your-api-key'
# Protect content
result = Daon.protect(
'My creative work',
title: 'My Story',
author: 'Author Name',
license: 'liberation_v1'
)
puts "Protected: #{result.verification_url}"
PHP
use Daon\DaonClient;
$daon = new DaonClient('your-api-key');
// Protect content
$result = $daon->protect(
'My creative work',
['title' => 'My Story', 'author' => 'Author Name'],
'liberation_v1'
);
echo "Protected: " . $result->verification_url;
Go
package main
import (
"github.com/daon-network/go-sdk"
)
func main() {
client := daon.NewClient("your-api-key")
result, err := client.Protect(daon.ProtectionRequest{
Content: "My creative work",
Metadata: map[string]string{
"title": "My Story",
"author": "Author Name",
},
License: "liberation_v1",
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Protected: %s\n", result.VerificationURL)
}
🧪 Testing
Sandbox Environment
Base URL: https://sandbox-api.daon.network/v1/
API Key: sk_test_1234567890abcdef
Features:
- No blockchain writes (faster testing)
- Reset data monthly
- Unlimited requests for testing
- Same API interface as production
Test API Key
curl -X POST https://sandbox-api.daon.network/v1/protect \
-H "Authorization: Bearer sk_test_1234567890abcdef" \
-H "Content-Type: application/json" \
-d '{
"content": "Test content for API testing",
"metadata": {"title": "Test Work"},
"license": "liberation_v1"
}'
📞 Support
API Support
- Documentation Issues: GitHub Issues
- API Bugs: api-support@daon.network
- Rate Limit Increases: Contact Sales
Developer Resources
- Stack Overflow: Tag questions with
daon-api - Status Page: api.daon.network/health
Ready to integrate DAON protection? Every API call is an act of creator protection. 🛡️