Back to use cases
platformOngoing

Power Your Legal AI Platform

Integrate the Moonlit Data API as the legal knowledge layer for your commercial legal AI product.

PlatformB2BData Licensing

What you'll build

If you are building a legal AI product -- whether it is a contract analysis tool, a compliance platform, a legal research application, or an AI assistant for lawyers -- the Moonlit API provides the comprehensive European legal data layer your product needs. Instead of building and maintaining your own legal data infrastructure (scraping court databases, parsing legislation, building search indices, handling multi-jurisdictional data models), you can use the Moonlit API as your production backend. We handle data ingestion from 50+ European legal sources, maintain search indices with semantic embeddings, and provide structured document retrieval with AI-generated summaries. This guide covers the architecture patterns, scaling considerations, and reliability strategies for using the Moonlit API as a commercial data provider. Contact us for enterprise pricing, SLAs, and dedicated support.

Architecture


  ┌───────────────────────────────────────────────────┐
  │              Your Legal AI Product                   │
  │  ┌──────────┐  ┌────────────┐  ┌───────────────┐  │
  │  │ Frontend │  │ Your       │  │ Your AI /     │  │
  │  │          │  │ Backend    │  │ LLM Layer     │  │
  │  └──────────┘  └──────┬─────┘  └───────────────┘  │
  └───────────────────────┼───────────────────────────┘
                         │
                         ▼
  ┌───────────────────────────────────────────────────┐
  │              Moonlit Data API                        │
  │  Search  |  Filters  |  Documents  |  Luna AI       │
  │  50+ EU Sources | Semantic Embeddings | AI Summaries │
  └───────────────────────────────────────────────────┘

Prerequisites

  • An existing legal AI product or product concept
  • A backend that can make server-side API calls
  • Contact sales@moonlit.ai for enterprise API access

Step-by-step

1

Choose your architecture pattern

The recommended approach is a proxy pattern: route all Moonlit requests through your backend. This gives you full control over caching, access control, and usage tracking. Never expose the Moonlit API key to your frontend.

// Your backend proxies Moonlit API calls
// Adds caching, auth, logging, and usage tracking

import { Redis } from "ioredis";

const redis = new Redis();
const CACHE_TTL = 3600; // 1 hour

export async function searchLegal(params: Record<string, unknown>) {
  const cacheKey = `moonlit:search:${JSON.stringify(params)}`;

  // Check cache first
  const cached = await redis.get(cacheKey);
  if (cached) return JSON.parse(cached);

  // Forward to Moonlit
  const response = await fetch(
    "https://api.moonlit.ai/v1.1/search/hybrid_search_reranked",
    {
      method: "POST",
      headers: {
        "Ocp-Apim-Subscription-Key": process.env.MOONLIT_API_KEY!,
        "Content-Type": "application/json",
      },
      body: JSON.stringify(params),
    },
  );

  const data = await response.json();
  await redis.setex(cacheKey, CACHE_TTL, JSON.stringify(data));
  return data;
}
2

Implement tiered caching

Cache filter endpoints aggressively (they change infrequently), cache search results with shorter TTLs, and cache retrieved documents for the longest duration.

const CACHE_TIERS = {
  filters: 86400,      // 24 hours -- jurisdictions, doc types change rarely
  search: 1800,        // 30 min -- results change as new docs are ingested
  documents: 604800,   // 7 days -- individual documents rarely change
};

// Prefetch filters on startup to warm the cache
async function warmFilterCache() {
  const endpoints = [
    "/search/filters/documenttypes",
    "/search/filters/jurisdictions_portals",
    "/search/filters/trees",
    "/search/semantic_portals",
  ];

  await Promise.all(
    endpoints.map(async (path) => {
      const res = await fetch(`https://api.moonlit.ai/v1.1${path}`, {
        headers: { "Ocp-Apim-Subscription-Key": process.env.MOONLIT_API_KEY! },
      });
      const data = await res.json();
      await redis.setex(`moonlit:${path}`, CACHE_TIERS.filters, JSON.stringify(data));
    }),
  );
}
3

Add resilience with retry and circuit breaker

Implement exponential backoff for transient errors and a circuit breaker pattern to gracefully degrade when the API is temporarily unavailable.

class MoonlitClient {
  private failureCount = 0;
  private circuitOpen = false;
  private lastFailure = 0;

  async request(path: string, options: RequestInit = {}) {
    // Circuit breaker: skip requests if too many recent failures
    if (this.circuitOpen) {
      if (Date.now() - this.lastFailure > 30000) {
        this.circuitOpen = false; // Try again after 30s cooldown
      } else {
        throw new Error("Circuit open -- Moonlit API temporarily unavailable");
      }
    }

    for (let attempt = 0; attempt < 3; attempt++) {
      try {
        const res = await fetch(`https://api.moonlit.ai/v1.1${path}`, {
          ...options,
          headers: {
            "Ocp-Apim-Subscription-Key": process.env.MOONLIT_API_KEY!,
            ...options.headers,
          },
        });

        if (res.status === 429) {
          const retryAfter = parseInt(res.headers.get("Retry-After") || "5");
          await new Promise((r) => setTimeout(r, retryAfter * 1000));
          continue;
        }

        if (!res.ok) throw new Error(`API error: ${res.status}`);

        this.failureCount = 0;
        return res.json();
      } catch (err) {
        this.failureCount++;
        if (this.failureCount >= 5) {
          this.circuitOpen = true;
          this.lastFailure = Date.now();
        }
        if (attempt === 2) throw err;
        await new Promise((r) => setTimeout(r, Math.pow(2, attempt) * 1000));
      }
    }
  }
}
4

Contact us for enterprise terms

For production integrations, we offer enterprise plans with higher rate limits, guaranteed SLAs, dedicated support, bulk data access, and custom data licensing terms. Email sales@moonlit.ai or use the contact form on our website to discuss your requirements.

What's next