Skip to main content

API Overview

SDD Classification: L3-Technical Authority: Engineering Team Review Cycle: Quarterly
Materi provides comprehensive REST and WebSocket APIs that enable you to integrate document collaboration, AI generation, and real-time editing into your applications. Build custom workflows, automate content creation, and embed Materi’s capabilities directly into your products.

API Architecture

Key API Features

FeatureDescription
RESTful DesignStandard HTTP methods and status codes
JSON-FirstAll requests and responses use JSON
Real-time WebSocketsLive collaboration and updates
JWT AuthenticationTokens with refresh capabilities
Rate LimitingFair usage policies with burst allowances
Webhook SupportEvent-driven integrations
Multi-language SDKsOfficial libraries for popular languages

Base URLs

Production Environment

PropertyValue
Base URLhttps://api.materi.dev/v1
WebSocket URLwss://api.materi.dev/v1/ws
RegionGlobal with edge caching
TLSRequired (TLS 1.3)

Development Environment

PropertyValue
Base URLhttps://api-staging.materi.dev/v1
WebSocket URLwss://api-staging.materi.dev/v1/ws
PurposeTesting and development
DataIsolated from production

Authentication Overview

Materi uses JWT (JSON Web Tokens) for secure, stateless authentication across all API endpoints.

Token Types

Token TypeExpirationPurpose
Access Token15 minutesAPI request authorization
Refresh Token30 daysObtain new access tokens
Collaboration Token60 minutesWebSocket sessions

Authentication Methods

Method A: User Authentication (OAuth 2.0) For applications acting on behalf of users with delegated authorization.
// Redirect user to authorization URL
const authUrl = `https://api.materi.dev/oauth/authorize?
  client_id=${CLIENT_ID}&
  response_type=code&
  scope=documents:read documents:write&
  redirect_uri=${CALLBACK_URL}`;

// Exchange authorization code for tokens
const response = await fetch("https://api.materi.dev/oauth/token", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
        grant_type: "authorization_code",
        client_id: CLIENT_ID,
        client_secret: CLIENT_SECRET,
        code: authorizationCode,
        redirect_uri: CALLBACK_URL,
    }),
});

const { access_token, refresh_token } = await response.json();
Method B: Service Authentication (Client Credentials) For server-to-server integrations without user context.
// For server-to-server integrations
const response = await fetch("https://api.materi.dev/oauth/token", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
        grant_type: "client_credentials",
        client_id: CLIENT_ID,
        client_secret: CLIENT_SECRET,
        scope: "documents:read workspaces:read",
    }),
});

const { access_token } = await response.json();

Using Access Tokens

Include the token in the Authorization header for all API requests:
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...

Rate Limiting

Rate Limits by Plan

PlanRequests/HourBurst AllowanceAI Requests/Day
Free1,000100100
Professional10,0005001,000
EnterpriseCustomCustomUnlimited

Rate Limit Headers

Every API response includes rate limit information:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 742
X-RateLimit-Reset: 1609459200
X-RateLimit-Retry-After: 3600

Handling Rate Limits

const rateLimitedApiCall = async (endpoint, options = {}) => {
    const response = await fetch(`https://api.materi.dev/v1${endpoint}`, {
        ...options,
        headers: {
            Authorization: `Bearer ${accessToken}`,
            "Content-Type": "application/json",
        },
    });

    if (response.status === 429) {
        const retryAfter = parseInt(response.headers.get("X-RateLimit-Retry-After"));
        console.warn(`Rate limit exceeded. Retry after ${retryAfter} seconds`);

        // Implement exponential backoff
        await new Promise((resolve) => setTimeout(resolve, retryAfter * 1000));
        return rateLimitedApiCall(endpoint, options);
    }

    return response.json();
};

Error Handling

Standard Error Response Format

All API errors follow a consistent format:
{
    "error": {
        "code": "DOCUMENT_NOT_FOUND",
        "message": "The requested document could not be found",
        "details": {
            "document_id": "123e4567-e89b-12d3-a456-426614174000",
            "workspace_id": "workspace_abc123"
        },
        "request_id": "req_1234567890abcdef",
        "timestamp": "2025-01-15T10:30:00Z"
    }
}

HTTP Status Codes

StatusMeaningCommon Causes
200SuccessRequest completed successfully
201CreatedResource created successfully
400Bad RequestInvalid request format or parameters
401UnauthorizedMissing or invalid authentication
403ForbiddenInsufficient permissions
404Not FoundResource doesn’t exist
409ConflictResource conflict (e.g., concurrent edit)
422Unprocessable EntityValid format but invalid data
429Rate LimitedToo many requests
500Server ErrorInternal server error
503Service UnavailableTemporary service outage

Error Codes Reference

Authentication Errors:
  • INVALID_TOKEN - JWT token is malformed or expired
  • INSUFFICIENT_PERMISSIONS - User lacks required permissions
  • ACCOUNT_SUSPENDED - User account is temporarily disabled
Resource Errors:
  • DOCUMENT_NOT_FOUND - Document ID doesn’t exist or no access
  • WORKSPACE_NOT_FOUND - Workspace doesn’t exist or no access
  • USER_NOT_FOUND - User ID doesn’t exist in workspace
Validation Errors:
  • INVALID_DOCUMENT_CONTENT - Document content format is invalid
  • TITLE_TOO_LONG - Document title exceeds maximum length
  • INVALID_EMAIL_FORMAT - Email address format is incorrect
Conflict Errors:
  • DOCUMENT_LOCKED - Document is locked by another operation
  • VERSION_CONFLICT - Document version has changed during edit
  • DUPLICATE_RESOURCE - Resource with same identifier already exists

Quick Start Example

class MateriAPI {
    constructor(accessToken) {
        this.baseURL = "https://api.materi.dev/v1";
        this.accessToken = accessToken;
    }

    async request(endpoint, options = {}) {
        const response = await fetch(`${this.baseURL}${endpoint}`, {
            ...options,
            headers: {
                Authorization: `Bearer ${this.accessToken}`,
                "Content-Type": "application/json",
                ...options.headers,
            },
        });

        if (!response.ok) {
            const error = await response.json();
            throw new Error(`API Error ${response.status}: ${error.error.message}`);
        }

        return response.json();
    }

    // Document operations
    async getDocuments(workspaceId = null) {
        const params = workspaceId ? `?workspace_id=${workspaceId}` : "";
        return this.request(`/documents${params}`);
    }

    async createDocument(data) {
        return this.request("/documents", {
            method: "POST",
            body: JSON.stringify(data),
        });
    }

    async getDocument(documentId) {
        return this.request(`/documents/${documentId}`);
    }

    async updateDocument(documentId, data) {
        return this.request(`/documents/${documentId}`, {
            method: "PATCH",
            body: JSON.stringify(data),
        });
    }

    // AI generation
    async generateContent(prompt, options = {}) {
        return this.request("/ai/generate", {
            method: "POST",
            body: JSON.stringify({ prompt, ...options }),
        });
    }
}

// Usage example
const api = new MateriAPI("your_access_token_here");

// Create a new document
const newDocument = await api.createDocument({
    title: "My API Document",
    content: "This document was created via the Materi API!",
    workspace_id: "workspace_123",
});

console.log("Created document:", newDocument.id);

// Generate AI content
const aiContent = await api.generateContent(
    "Write a summary of renewable energy benefits",
    { max_tokens: 500 }
);

console.log("Generated content:", aiContent.content);

SDKs and Libraries

Official SDKs

JavaScript/TypeScript
npm install @materi/api-client
import { MateriAPI } from "@materi/api-client";

const client = new MateriAPI({
    accessToken: "your_token",
    environment: "production",
});

const documents = await client.documents.list();
Python
pip install materi-python
from materi import MateriClient

client = MateriClient(access_token='your_token')
documents = client.documents.list()
Go
go get github.com/materi/materi-go
import "github.com/materi/materi-go"

client := materi.NewClient("your_token")
documents, err := client.Documents.List(ctx)

API Endpoints Summary

Documents

MethodEndpointDescription
POST/api/v1/documentsCreate document
GET/api/v1/documents/{id}Get document
PATCH/api/v1/documents/{id}Update document
DELETE/api/v1/documents/{id}Delete document
GET/api/v1/documentsList documents
GET/api/v1/documents/searchSearch documents

AI Operations

MethodEndpointDescription
POST/api/v1/ai/generateGenerate content (SSE)
POST/api/v1/ai/completeAutocomplete
GET/api/v1/ai/suggestionsGet AI suggestions

Collaboration

MethodEndpointDescription
WS/api/v1/collab/document/{id}WebSocket connection
GET/api/v1/collab/presence/{id}Active users

Authentication

MethodEndpointDescription
POST/api/v1/auth/refreshRefresh access token
POST/api/v1/auth/logoutRevoke tokens

Health & Monitoring

MethodEndpointDescription
GET/healthHealth check
GET/readyReadiness check
GET/metricsPrometheus metrics


Document Status: Complete Version: 2.0