Skip to main content
Glama
PaperlessAPI.ts8.65 kB
import axios from "axios"; import FormData from "form-data"; import { BulkEditDocumentsResult, BulkEditParameters, Correspondent, CustomField, Document, DocumentsResponse, DocumentType, GetCorrespondentsResponse, GetCustomFieldsResponse, GetDocumentTypesResponse, GetTagsResponse, Tag, } from "./types"; import { headersToObject } from "./utils"; export class PaperlessAPI { constructor( private readonly baseUrl: string, private readonly token: string ) { this.baseUrl = baseUrl; this.token = token; } async request<T = any>(path: string, options: RequestInit = {}) { const url = `${this.baseUrl}/api${path}`; const isJson = !options.body || typeof options.body === "string"; const mergedHeaders = { Authorization: `Token ${this.token}`, Accept: "application/json; version=5", "Accept-Language": "en-US,en;q=0.9", ...(isJson ? { "Content-Type": "application/json" } : {}), ...headersToObject(options.headers), }; try { const response = await axios<T>({ url, method: options.method || "GET", headers: mergedHeaders, data: options.body, }); const body = response.data; if (response.status < 200 || response.status >= 300) { console.error({ error: "Error executing request", url, options, status: response.status, response: body, }); const errorMessage = (body as Record<string, unknown>)?.detail || (body as Record<string, unknown>)?.error || (body as Record<string, unknown>)?.message || `HTTP error! status: ${response.status}`; throw new Error(String(errorMessage)); } return body; } catch (error) { console.error({ error: "Error executing request", message: error instanceof Error ? error.message : String(error), url, options, responseData: (error as any)?.response?.data, status: (error as any)?.response?.status, }); throw error; } } // Document operations async bulkEditDocuments( documents: number[], method: string, parameters: BulkEditParameters = {} ): Promise<BulkEditDocumentsResult> { return this.request<BulkEditDocumentsResult>("/documents/bulk_edit/", { method: "POST", body: JSON.stringify({ documents, method, parameters, }), }); } async postDocument( file: File, metadata: Record<string, string | string[] | number | number[]> = {} ): Promise<string> { const formData = new FormData(); formData.append("document", file); // Add optional metadata fields if (metadata.title) formData.append("title", metadata.title); if (metadata.created) formData.append("created", metadata.created); if (metadata.correspondent) formData.append("correspondent", metadata.correspondent); if (metadata.document_type) formData.append("document_type", metadata.document_type); if (metadata.storage_path) formData.append("storage_path", metadata.storage_path); if (metadata.tags) { (metadata.tags as string[]).forEach((tag) => formData.append("tags", tag) ); } if (metadata.archive_serial_number) { formData.append("archive_serial_number", metadata.archive_serial_number); } if (metadata.custom_fields) { (metadata.custom_fields as string[]).forEach((field) => formData.append("custom_fields", field) ); } const response = await axios.post<string>( `${this.baseUrl}/api/documents/post_document/`, formData, { headers: { Authorization: `Token ${this.token}`, ...formData.getHeaders(), }, } ); if (response.status < 200 || response.status >= 300) { throw new Error(`HTTP error! status: ${response.status}`); } return response.data; } async getDocuments(query = ""): Promise<DocumentsResponse> { return this.request<DocumentsResponse>(`/documents/${query}`); } async getDocument(id: number): Promise<Document> { return this.request<Document>(`/documents/${id}/`); } async updateDocument(id: number, data: Partial<Document>): Promise<Document> { return this.request<Document>(`/documents/${id}/`, { method: "PATCH", body: JSON.stringify(data), }); } async searchDocuments(query: string): Promise<DocumentsResponse> { const response = await this.request<DocumentsResponse>( `/documents/?query=${encodeURIComponent(query)}` ); return response; } async downloadDocument(id: number, asOriginal = false) { const query = asOriginal ? "?original=true" : ""; const response = await axios.get( `${this.baseUrl}/api/documents/${id}/download/${query}`, { headers: { Authorization: `Token ${this.token}`, }, responseType: "arraybuffer", } ); return response; } // Tag operations async getTags(): Promise<GetTagsResponse> { return this.request<GetTagsResponse>("/tags/"); } async createTag(data: Partial<Tag>): Promise<Tag> { return this.request<Tag>("/tags/", { method: "POST", body: JSON.stringify(data), }); } async updateTag(id: number, data: Partial<Tag>): Promise<Tag> { return this.request<Tag>(`/tags/${id}/`, { method: "PUT", body: JSON.stringify(data), }); } async deleteTag(id: number): Promise<void> { return this.request<void>(`/tags/${id}/`, { method: "DELETE", }); } // Correspondent operations async getCorrespondents( queryString?: string ): Promise<GetCorrespondentsResponse> { const url = queryString ? `/correspondents/?${queryString}` : "/correspondents/"; return this.request<GetCorrespondentsResponse>(url); } async getCorrespondent(id: number): Promise<Correspondent> { return this.request<Correspondent>(`/correspondents/${id}/`); } async createCorrespondent( data: Partial<Correspondent> ): Promise<Correspondent> { return this.request<Correspondent>("/correspondents/", { method: "POST", body: JSON.stringify(data), }); } async updateCorrespondent( id: number, data: Partial<Correspondent> ): Promise<Correspondent> { return this.request<Correspondent>(`/correspondents/${id}/`, { method: "PUT", body: JSON.stringify(data), }); } async deleteCorrespondent(id: number): Promise<void> { return this.request<void>(`/correspondents/${id}/`, { method: "DELETE", }); } // Document type operations async getDocumentTypes(): Promise<GetDocumentTypesResponse> { return this.request<GetDocumentTypesResponse>("/document_types/"); } async createDocumentType(data: Partial<DocumentType>): Promise<DocumentType> { return this.request<DocumentType>("/document_types/", { method: "POST", body: JSON.stringify(data), }); } async updateDocumentType( id: number, data: Partial<DocumentType> ): Promise<DocumentType> { return this.request<DocumentType>(`/document_types/${id}/`, { method: "PUT", body: JSON.stringify(data), }); } async deleteDocumentType(id: number): Promise<void> { return this.request<void>(`/document_types/${id}/`, { method: "DELETE", }); } // Custom field operations async getCustomFields(): Promise<GetCustomFieldsResponse> { return this.request<GetCustomFieldsResponse>("/custom_fields/"); } async getCustomField(id: number): Promise<CustomField> { return this.request<CustomField>(`/custom_fields/${id}/`); } async createCustomField(data: Partial<CustomField>): Promise<CustomField> { return this.request<CustomField>("/custom_fields/", { method: "POST", body: JSON.stringify(data), }); } async updateCustomField( id: number, data: Partial<CustomField> ): Promise<CustomField> { return this.request<CustomField>(`/custom_fields/${id}/`, { method: "PUT", body: JSON.stringify(data), }); } async deleteCustomField(id: number): Promise<void> { return this.request<void>(`/custom_fields/${id}/`, { method: "DELETE", }); } // Bulk object operations async bulkEditObjects(objects, objectType, operation, parameters = {}) { return this.request("/bulk_edit_objects/", { method: "POST", body: JSON.stringify({ objects, object_type: objectType, operation, ...parameters, }), }); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/baruchiro/paperless-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server