# Code Examples & SDKs

Real-world integration patterns and best practices for the WEIR API v2.

### Discover Available Licenses

Use the metadata discovery endpoints to find licensable identities without authentication

Metadata endpoints are public and rate-limited to 10 requests/minute. See [Metadata Discovery](/content/developers/metadata/index.html) for details.

JavaScriptPythoncURL

```javascript
// Discover all public licenses via metadata endpoint (no auth required)
async function discoverLicenses(query = '') {
  const url = new URL('https://wapi.weir.ai/metadata');
  if (query) url.searchParams.set('q', query);
  url.searchParams.set('format', 'json');

const response = await fetch(url);
  const data = await response.json();

return data.licenses; // Array of public licenses with terms
}

// Search for specific identity
const results = await discoverLicenses('musician');
console.log(`Found ${results.length} licensable identities`);

// Each license includes:
// - id, external_id, title, description
// - license_type, status
// - rate_card (pricing tiers)
// - platforms_config (allowed/blocked platforms)
```

### Mobile App Authentication

Authenticate mobile apps using bundle ID verification

Mobile API keys require admin verification before use. Submit your app for review in Settings → Developer.

Swift (iOS)Kotlin (Android)

```swift
import Foundation

class WEIRClient {
    private let apiKey: String
    private let apiSecret: String
    private let bundleId: String
    private var accessToken: String?

init() {
        self.apiKey = Bundle.main.object(forInfoDictionaryKey: "WEIR_API_KEY") as! String
        self.apiSecret = Bundle.main.object(forInfoDictionaryKey: "WEIR_API_SECRET") as! String
        self.bundleId = Bundle.main.bundleIdentifier!
    }

func authenticate() async throws -> String {
        var request = URLRequest(url: URL(string: "https://wapi.weir.ai/auth/token")!)
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.setValue(bundleId, forHTTPHeaderField: "X-Bundle-ID"); // Required!

let body = ["api_key": apiKey, "api_secret": apiSecret]
        request.httpBody = try JSONEncoder().encode(body)

let (data, _) = try await URLSession.shared.data(for: request)
        let response = try JSONDecoder().decode(AuthResponse.self, from: data)

self.accessToken = response.accessToken
        return response.accessToken
    }
}
```

### Create and Publish a License

Programmatically create and publish identity licenses via API v2

JavaScriptPython

```javascript
async function createAndPublishLicense(accessToken, licenseData) {
  // Create license (draft status)
  const createResponse = await fetch(
    'https://wapi.weir.ai/licenses',
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${accessToken}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        title: licenseData.title,
        description: licenseData.description,
        license_type: 'commercial',
        rate_card: {
          social_media: 100,
          commercial: 500,
          ai_training: 1000
        },
        platforms_config: {
          allowed: ['instagram', 'youtube', 'tiktok'],
          blocked: []
        }
      })
    }
  );

const { data: license } = await createResponse.json();

// Publish the license by updating status
  const publishResponse = await fetch(
    `https://wapi.weir.ai/licenses/${license.id}`,
    {
      method: 'PATCH',
      headers: {
        'Authorization': `Bearer ${accessToken}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ status: 'public' })
    }
  );

return publishResponse.json();
}

// Usage
const license = await createAndPublishLicense(token, {
  title: 'Commercial License - Full Rights',
  description: 'License for commercial use of my identity'
});
console.log('Published:', license.data.external_id);
```

### Query License Mentions

Retrieve and filter mentions detected for your licenses

JavaScriptcURL

```javascript
async function getLicenseMentions(accessToken, licenseId, options = {}) {
  const params = new URLSearchParams();
  if (options.status) params.set('status', options.status);
  if (options.limit) params.set('limit', options.limit);
  if (options.offset) params.set('offset', options.offset);

const response = await fetch(
    `https://wapi.weir.ai/licenses/${licenseId}/mentions?${params}`,
    {
      headers: { 'Authorization': `Bearer ${accessToken}` }
    }
  );

return response.json();
}

// Get all pending mentions
const { data: mentions, pagination } = await getLicenseMentions(
  token,
  'lic_abc123',
  { status: 'pending', limit: 50 }
);

console.log(`Found ${pagination.total} pending mentions`);

// Update mention status
await fetch(`https://wapi.weir.ai/mentions/${mentions[0].id}`, {
  method: 'PATCH',
  headers: {
    'Authorization': `Bearer ${token}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    status: 'confirmed',
    is_flagged: true // Flag for claim creation
  })
});
```

### Set Up Webhook Notifications

Receive real-time notifications when mentions are detected

Manage webhooks in [Settings → Developer → Webhooks](/content/developers/webhooks/index.html). All payloads are signed with HMAC-SHA256.

Webhook HandlerEvent Types

```javascript
import crypto from 'crypto';
import express from 'express';

const app = express();
const WEBHOOK_SECRET = process.env.WEIR_WEBHOOK_SECRET;

// Verify webhook signature
function verifySignature(payload, signature) {
  const expected = crypto
    .createHmac('sha256', WEBHOOK_SECRET)
    .update(payload)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(`sha256=${expected}`)
  );
}

app.post('/webhooks/weir', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-weir-signature'];

if (!verifySignature(req.body, signature)) {
    return res.status(401).send('Invalid signature');
  }

const event = JSON.parse(req.body);

switch (event.type) {
    case 'mention.detected':
      console.log('New mention:', event.data.content_url);
      // Process new mention...
      break;
    case 'license.updated':
      console.log('License updated:', event.data.license_id);
      break;
  }

res.status(200).send('OK');
});
```

### Rate Limits & Best Practices

#### Rate Limits by Tier

- • **Free:** 100 requests/hour, 1,000 requests/day
- • **Pro:** 1,000 requests/hour, 10,000 requests/day
- • **Enterprise:** Custom limits available
- • **Metadata endpoints:** 10 requests/minute (unauthenticated)

#### Response Headers

```
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 847
X-RateLimit-Reset: 1733234400
```

#### Best Practices

- • **Use metadata discovery** instead of polling the licenses endpoint
- • **Set up webhooks** for real-time mention notifications
- • Cache license data locally and refresh on webhook events
- • Implement exponential backoff for retries (start at 1s, max 32s)
- • Monitor rate limit headers to avoid hitting limits
