Version: 1.0.0
Last Updated: February 20, 2026
Status: Production Ready
https://your-domain.com/api
All endpoints require authentication via Clerk. Include the user ID in the request header:
x-user-id: <user-id>
Analyzes a contract and returns risk assessment.
Endpoint: POST /contract-analyzer
Request:
{
"contractText": "string (required, min 50 chars)",
"contractType": "string (optional)",
"userId": "string (optional)"
}Response (200 OK):
{
"overallRisk": 68,
"riskLevel": "Moderate Risk",
"confidence": 94,
"analysisTime": 2.3,
"redFlags": [
{
"clause": "Broad indemnity clause",
"section": "5.2",
"issue": "You're liable for everything",
"suggestion": "Cap at 1x contract value"
}
],
"warnings": [
{
"clause": "One-sided termination",
"section": "8.1",
"issue": "They can exit anytime, you can't",
"suggestion": "Add 30-day notice requirement"
}
],
"suggestedRevisions": [
"Add liability cap: 'Liability limited to contract value'",
"Add mutual termination: 'Either party may terminate with 30 days notice'",
"Add indemnity cap: 'Indemnity capped at 1x annual fees'"
]
}Error Responses:
-
400 Bad Request: Invalid contract text{ "error": "Contract text too short. Please provide at least 50 characters." } -
429 Too Many Requests: Query limit exceeded{ "error": "Daily query limit reached", "remaining": 0, "message": "Upgrade to Pro for unlimited access" } -
500 Internal Server Error: Server error{ "error": "Failed to analyze contract" }
Rate Limits:
- Free tier: 5 queries/day
- Pro tier: Unlimited
- Enterprise: Unlimited
Example:
curl -X POST https://your-domain.com/api/contract-analyzer \
-H "Content-Type: application/json" \
-d '{
"contractText": "This is a sample contract...",
"contractType": "employment",
"userId": "user-123"
}'Retrieves dashboard metrics for admin users.
Endpoint: GET /admin/analytics
Authentication: Admin only
Response (200 OK):
{
"totalQueries": 1247,
"dailyQueries": 89,
"activeUsers": 234,
"conversionRate": 12.3,
"mrr": 4560,
"growthRate": 23,
"domainDistribution": [
{
"domain": "Employment",
"count": 423,
"percentage": 34
},
{
"domain": "NDAs",
"count": 348,
"percentage": 28
},
{
"domain": "Service Agreements",
"count": 274,
"percentage": 22
},
{
"domain": "Licensing",
"count": 149,
"percentage": 12
},
{
"domain": "Other",
"count": 53,
"percentage": 4
}
],
"errorRate": 0.2,
"avgAnalysisTime": 2.1,
"userRetention": 78
}Error Responses:
401 Unauthorized: Not authenticated403 Forbidden: Not admin user500 Internal Server Error: Server error
Caching: 5 minutes
Example:
curl -X GET https://your-domain.com/api/admin/analytics \
-H "x-user-id: admin-user-123"Retrieves current subscription details.
Endpoint: GET /api/subscription
Response (200 OK):
{
"id": "sub-123",
"userId": "user-123",
"tier": "free",
"status": "active",
"queriesUsed": 3,
"queriesLimit": 5,
"stripeCustomerId": null,
"stripeSubscriptionId": null,
"createdAt": "2026-02-20T10:00:00Z",
"expiresAt": null,
"lastResetAt": "2026-02-20T00:00:00Z"
}Creates or updates a subscription.
Endpoint: POST /api/subscription
Request:
{
"userId": "string (required)",
"tier": "free|pro|enterprise (required)",
"stripeCustomerId": "string (optional)",
"stripeSubscriptionId": "string (optional)"
}Response (200 OK):
{
"id": "sub-456",
"userId": "user-123",
"tier": "pro",
"status": "active",
"queriesUsed": 0,
"queriesLimit": 999999,
"stripeCustomerId": "cus_123",
"stripeSubscriptionId": "sub_123",
"createdAt": "2026-02-20T10:00:00Z",
"expiresAt": "2026-03-20T10:00:00Z",
"lastResetAt": "2026-02-20T00:00:00Z"
}Error Responses:
-
400 Bad Request: Invalid tier{ "error": "Invalid tier" } -
401 Unauthorized: User ID required{ "error": "User ID required" }
Example:
curl -X POST https://your-domain.com/api/subscription \
-H "Content-Type: application/json" \
-d '{
"userId": "user-123",
"tier": "pro",
"stripeCustomerId": "cus_123",
"stripeSubscriptionId": "sub_123"
}'interface RiskAnalysis {
overallRisk: number // 0-100
riskLevel: string // "Low Risk", "Moderate Risk", "High Risk"
confidence: number // 0-100
analysisTime: number // seconds
redFlags: RedFlag[]
warnings: Warning[]
suggestedRevisions: string[]
}
interface RedFlag {
clause: string
section: string
issue: string
suggestion: string
}
interface Warning {
clause: string
section: string
issue: string
suggestion: string
}interface Subscription {
id: string
userId: string
tier: "free" | "pro" | "enterprise"
status: "active" | "cancelled" | "expired"
queriesUsed: number
queriesLimit: number
stripeCustomerId?: string
stripeSubscriptionId?: string
createdAt: Date
expiresAt?: Date
lastResetAt?: Date
}interface AnalyticsMetrics {
totalQueries: number
dailyQueries: number
activeUsers: number
conversionRate: number
mrr: number
growthRate: number
domainDistribution: DomainCount[]
errorRate: number
avgAnalysisTime: number
userRetention: number
}
interface DomainCount {
domain: string
count: number
percentage: number
}{
"error": "Error message",
"status": 400,
"timestamp": "2026-02-20T10:00:00Z"
}400 Bad Request: Invalid input401 Unauthorized: Authentication required403 Forbidden: Permission denied404 Not Found: Resource not found429 Too Many Requests: Rate limit exceeded500 Internal Server Error: Server error
- 5 queries per day
- Resets at midnight UTC
- Returns 429 when exceeded
- Unlimited queries
- No rate limiting
- Unlimited queries
- Custom rate limits available
Not yet implemented. All responses return complete data.
customer.subscription.createdcustomer.subscription.updatedcustomer.subscription.deletedinvoice.payment_succeededinvoice.payment_failed
Content-Type: application/json
x-user-id: <user-id>
Authorization: Bearer <token> (if applicable)
const response = await fetch('/api/contract-analyzer', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-user-id': userId
},
body: JSON.stringify({
contractText: text,
contractType: 'employment'
})
})
if (!response.ok) {
const error = await response.json()
console.error('Error:', error.error)
return
}
const data = await response.json()
console.log('Analysis:', data)try {
const response = await fetch('/api/contract-analyzer', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ contractText })
})
if (response.status === 429) {
// Show upgrade prompt
showUpgradeModal()
} else if (!response.ok) {
// Handle other errors
const error = await response.json()
showError(error.error)
} else {
const data = await response.json()
displayAnalysis(data)
}
} catch (error) {
console.error('Network error:', error)
showError('Network error. Please try again.')
}import { ContractAnalyzer } from '@law-ai/sdk'
const analyzer = new ContractAnalyzer({
apiKey: 'your-api-key',
baseUrl: 'https://your-domain.com/api'
})
const result = await analyzer.analyze({
contractText: 'Your contract text...',
contractType: 'employment'
})
console.log(result.overallRisk) // 68from law_ai import ContractAnalyzer
analyzer = ContractAnalyzer(
api_key='your-api-key',
base_url='https://your-domain.com/api'
)
result = analyzer.analyze(
contract_text='Your contract text...',
contract_type='employment'
)
print(result['overall_risk']) # 68- Initial release
- Contract analyzer endpoint
- Admin analytics endpoint
- Subscription management
- Query limit enforcement
For API support, contact:
- Email: api-support@law-ai.com
- Slack: #api-support
- GitHub: github.com/law-ai/issues
API is available under the MIT License.