SyntaxdocSyntaxdoc

SDKs & Integration

Official SDKs and code examples for integrating SyntaxDoc

Integrate SyntaxDoc into your application with these code examples and libraries.

Note: Official SDKs are coming soon! In the meantime, use the REST API directly with these examples.


REST API Integration

SyntaxDoc uses a simple REST API with multipart/form-data requests. Here are complete integration examples:

/**
 * SyntaxDoc API Client
 * Simple wrapper for the SyntaxDoc PDF generation API
 */
class SyntaxDocClient {
  private apiKey: string;
  private baseUrl: string;

  constructor(apiKey: string, baseUrl = 'https://api.syntaxdoc.com') {
    this.apiKey = apiKey;
    this.baseUrl = baseUrl;
  }

  /**
   * Generate a PDF from HTML content
   */
  async generatePdf(
    htmlContent: string,
    options: {
      fileName?: string;
      format?: string;
      orientation?: 'portrait' | 'landscape';
      margin?: { top?: string; right?: string; bottom?: string; left?: string };
      host?: boolean;
    } = {}
  ): Promise<Blob | { url: string; pdfId: string; expiresAt: string }> {
    const formData = new FormData();
    const blob = new Blob([htmlContent], { type: 'text/html' });
    formData.append('files', blob, 'index.html');
    formData.append('options', JSON.stringify(options));

    const response = await fetch(`${this.baseUrl}/pdf/generate`, {
      method: 'POST',
      headers: { 'X-API-Key': this.apiKey },
      body: formData,
    });

    if (!response.ok) {
      const error = await response.json();
      throw new Error(error.message || 'PDF generation failed');
    }

    if (response.headers.get('content-type')?.includes('application/json')) {
      return response.json();
    }
    return response.blob();
  }

  /**
   * Generate PDF with external resources (CSS, images, fonts)
   */
  async generatePdfWithResources(
    files: { name: string; content: Blob | string; type: string }[],
    options: Record<string, any> = {}
  ): Promise<Blob | object> {
    const formData = new FormData();
    
    for (const file of files) {
      const blob = typeof file.content === 'string' 
        ? new Blob([file.content], { type: file.type })
        : file.content;
      formData.append('files', blob, file.name);
    }
    
    formData.append('options', JSON.stringify(options));

    const response = await fetch(`${this.baseUrl}/pdf/generate`, {
      method: 'POST',
      headers: { 'X-API-Key': this.apiKey },
      body: formData,
    });

    if (!response.ok) {
      const error = await response.json();
      throw new Error(error.message);
    }

    const contentType = response.headers.get('content-type');
    return contentType?.includes('application/json') 
      ? response.json() 
      : response.blob();
  }

  /**
   * Merge multiple PDF files
   */
  async mergePdfs(
    pdfFiles: File[],
    options: { fileName?: string; host?: boolean } = {}
  ): Promise<Blob | object> {
    const formData = new FormData();
    
    for (const file of pdfFiles) {
      formData.append('files', file);
    }
    
    formData.append('options', JSON.stringify(options));

    const response = await fetch(`${this.baseUrl}/pdf/merge`, {
      method: 'POST',
      headers: { 'X-API-Key': this.apiKey },
      body: formData,
    });

    if (!response.ok) {
      const error = await response.json();
      throw new Error(error.message);
    }

    const contentType = response.headers.get('content-type');
    return contentType?.includes('application/json') 
      ? response.json() 
      : response.blob();
  }
}

// Usage example
const client = new SyntaxDocClient('YOUR_API_KEY');

// Simple HTML to PDF
const pdf = await client.generatePdf('<h1>Hello World</h1>', {
  fileName: 'hello',
  format: 'A4',
});

// Host the PDF
const hosted = await client.generatePdf('<h1>Hosted PDF</h1>', {
  host: true,
});
console.log('PDF URL:', hosted.url);
"""
SyntaxDoc API Client
Simple wrapper for the SyntaxDoc PDF generation API
"""
import requests
import json
from typing import Optional, Dict, Any, Union, List
from pathlib import Path


class SyntaxDocClient:
    def __init__(self, api_key: str, base_url: str = 'https://api.syntaxdoc.com'):
        self.api_key = api_key
        self.base_url = base_url
        self.session = requests.Session()
        self.session.headers.update({'X-API-Key': api_key})

    def generate_pdf(
        self,
        html_content: str,
        file_name: str = 'document',
        format: str = 'A4',
        orientation: str = 'portrait',
        margin: Optional[Dict[str, str]] = None,
        host: bool = False
    ) -> Union[bytes, Dict[str, Any]]:
        """Generate a PDF from HTML content."""
        files = [('files', ('index.html', html_content, 'text/html'))]
        
        options = {
            'fileName': file_name,
            'format': format,
            'orientation': orientation,
            'host': host
        }
        if margin:
            options['margin'] = margin
        
        data = {'options': json.dumps(options)}
        
        response = self.session.post(
            f'{self.base_url}/pdf/generate',
            files=files,
            data=data
        )
        response.raise_for_status()
        
        if 'application/json' in response.headers.get('content-type', ''):
            return response.json()
        return response.content

    def generate_pdf_from_file(
        self,
        html_path: str,
        resource_paths: Optional[List[str]] = None,
        **options
    ) -> Union[bytes, Dict[str, Any]]:
        """Generate PDF from HTML file with optional resources."""
        files = []
        
        # Add main HTML file
        with open(html_path, 'rb') as f:
            files.append(('files', ('index.html', f.read(), 'text/html')))
        
        # Add resource files
        if resource_paths:
            for path in resource_paths:
                p = Path(path)
                mime_type = self._get_mime_type(p.suffix)
                with open(path, 'rb') as f:
                    files.append(('files', (p.name, f.read(), mime_type)))
        
        data = {'options': json.dumps(options)}
        
        response = self.session.post(
            f'{self.base_url}/pdf/generate',
            files=files,
            data=data
        )
        response.raise_for_status()
        
        if 'application/json' in response.headers.get('content-type', ''):
            return response.json()
        return response.content

    def merge_pdfs(
        self,
        pdf_paths: List[str],
        file_name: str = 'merged',
        host: bool = False
    ) -> Union[bytes, Dict[str, Any]]:
        """Merge multiple PDF files."""
        files = []
        for path in pdf_paths:
            with open(path, 'rb') as f:
                files.append(('files', (Path(path).name, f.read(), 'application/pdf')))
        
        data = {'options': json.dumps({'fileName': file_name, 'host': host})}
        
        response = self.session.post(
            f'{self.base_url}/pdf/merge',
            files=files,
            data=data
        )
        response.raise_for_status()
        
        if 'application/json' in response.headers.get('content-type', ''):
            return response.json()
        return response.content

    def _get_mime_type(self, extension: str) -> str:
        mime_types = {
            '.html': 'text/html',
            '.css': 'text/css',
            '.js': 'application/javascript',
            '.png': 'image/png',
            '.jpg': 'image/jpeg',
            '.jpeg': 'image/jpeg',
            '.svg': 'image/svg+xml',
            '.woff': 'font/woff',
            '.woff2': 'font/woff2',
            '.ttf': 'font/ttf',
        }
        return mime_types.get(extension.lower(), 'application/octet-stream')


# Usage example
if __name__ == '__main__':
    client = SyntaxDocClient('YOUR_API_KEY')
    
    # Simple HTML to PDF
    pdf_bytes = client.generate_pdf(
        '<h1>Hello World</h1>',
        file_name='hello',
        format='A4'
    )
    
    with open('hello.pdf', 'wb') as f:
        f.write(pdf_bytes)
    
    # Host the PDF
    result = client.generate_pdf('<h1>Hosted</h1>', host=True)
    print(f"PDF URL: {result['url']}")
<?php
/**
 * SyntaxDoc API Client
 * Simple wrapper for the SyntaxDoc PDF generation API
 */
class SyntaxDocClient
{
    private string $apiKey;
    private string $baseUrl;

    public function __construct(string $apiKey, string $baseUrl = 'https://api.syntaxdoc.com')
    {
        $this->apiKey = $apiKey;
        $this->baseUrl = $baseUrl;
    }

    /**
     * Generate a PDF from HTML content
     */
    public function generatePdf(
        string $htmlContent,
        array $options = []
    ): array|string {
        $options = array_merge([
            'fileName' => 'document',
            'format' => 'A4',
        ], $options);

        $boundary = uniqid();
        $body = $this->buildMultipartBody($boundary, [
            ['name' => 'files', 'filename' => 'index.html', 'content' => $htmlContent, 'type' => 'text/html'],
        ], $options);

        $response = $this->request('/pdf/generate', $body, $boundary);
        
        // Check if JSON response (hosted PDF)
        $decoded = json_decode($response, true);
        return $decoded !== null ? $decoded : $response;
    }

    /**
     * Generate PDF with external resources
     */
    public function generatePdfWithResources(array $files, array $options = []): array|string
    {
        $boundary = uniqid();
        $fileData = [];
        
        foreach ($files as $file) {
            $fileData[] = [
                'name' => 'files',
                'filename' => $file['name'],
                'content' => $file['content'],
                'type' => $file['type'] ?? 'application/octet-stream',
            ];
        }

        $body = $this->buildMultipartBody($boundary, $fileData, $options);
        $response = $this->request('/pdf/generate', $body, $boundary);
        
        $decoded = json_decode($response, true);
        return $decoded !== null ? $decoded : $response;
    }

    /**
     * Merge multiple PDF files
     */
    public function mergePdfs(array $pdfPaths, array $options = []): array|string
    {
        $boundary = uniqid();
        $fileData = [];
        
        foreach ($pdfPaths as $path) {
            $fileData[] = [
                'name' => 'files',
                'filename' => basename($path),
                'content' => file_get_contents($path),
                'type' => 'application/pdf',
            ];
        }

        $body = $this->buildMultipartBody($boundary, $fileData, $options);
        $response = $this->request('/pdf/merge', $body, $boundary);
        
        $decoded = json_decode($response, true);
        return $decoded !== null ? $decoded : $response;
    }

    private function request(string $endpoint, string $body, string $boundary): string
    {
        $ch = curl_init($this->baseUrl . $endpoint);
        
        curl_setopt_array($ch, [
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => $body,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => [
                'X-API-Key: ' . $this->apiKey,
                'Content-Type: multipart/form-data; boundary=' . $boundary,
            ],
        ]);

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($httpCode >= 400) {
            throw new Exception("API Error: " . $response);
        }

        return $response;
    }

    private function buildMultipartBody(string $boundary, array $files, array $options): string
    {
        $body = '';
        
        foreach ($files as $file) {
            $body .= "--{$boundary}\r\n";
            $body .= "Content-Disposition: form-data; name=\"{$file['name']}\"; filename=\"{$file['filename']}\"\r\n";
            $body .= "Content-Type: {$file['type']}\r\n\r\n";
            $body .= $file['content'] . "\r\n";
        }
        
        $body .= "--{$boundary}\r\n";
        $body .= "Content-Disposition: form-data; name=\"options\"\r\n\r\n";
        $body .= json_encode($options) . "\r\n";
        $body .= "--{$boundary}--\r\n";

        return $body;
    }
}

// Usage example
$client = new SyntaxDocClient('YOUR_API_KEY');

// Simple HTML to PDF
$pdf = $client->generatePdf('<h1>Hello World</h1>', [
    'fileName' => 'hello',
    'format' => 'A4',
]);

file_put_contents('hello.pdf', $pdf);

// Host the PDF
$result = $client->generatePdf('<h1>Hosted</h1>', ['host' => true]);
echo "PDF URL: " . $result['url'];
package syntaxdoc

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "mime/multipart"
    "net/http"
    "os"
    "path/filepath"
)

// Client is the SyntaxDoc API client
type Client struct {
    APIKey  string
    BaseURL string
    HTTP    *http.Client
}

// Options for PDF generation
type Options struct {
    FileName    string            `json:"fileName,omitempty"`
    Format      string            `json:"format,omitempty"`
    Orientation string            `json:"orientation,omitempty"`
    Margin      map[string]string `json:"margin,omitempty"`
    Host        bool              `json:"host,omitempty"`
}

// HostedPDF is the response when host=true
type HostedPDF struct {
    URL       string `json:"url"`
    PdfID     string `json:"pdfId"`
    ExpiresAt string `json:"expiresAt"`
}

// NewClient creates a new SyntaxDoc client
func NewClient(apiKey string) *Client {
    return &Client{
        APIKey:  apiKey,
        BaseURL: "https://api.syntaxdoc.com",
        HTTP:    &http.Client{},
    }
}

// GeneratePDF generates a PDF from HTML content
func (c *Client) GeneratePDF(html string, opts *Options) ([]byte, *HostedPDF, error) {
    body := &bytes.Buffer{}
    writer := multipart.NewWriter(body)

    // Add HTML file
    part, err := writer.CreateFormFile("files", "index.html")
    if err != nil {
        return nil, nil, err
    }
    part.Write([]byte(html))

    // Add options
    if opts != nil {
        optionsJSON, _ := json.Marshal(opts)
        writer.WriteField("options", string(optionsJSON))
    }

    writer.Close()

    req, err := http.NewRequest("POST", c.BaseURL+"/pdf/generate", body)
    if err != nil {
        return nil, nil, err
    }

    req.Header.Set("X-API-Key", c.APIKey)
    req.Header.Set("Content-Type", writer.FormDataContentType())

    resp, err := c.HTTP.Do(req)
    if err != nil {
        return nil, nil, err
    }
    defer resp.Body.Close()

    if resp.StatusCode >= 400 {
        bodyBytes, _ := io.ReadAll(resp.Body)
        return nil, nil, fmt.Errorf("API error: %s", string(bodyBytes))
    }

    // Check if JSON response (hosted PDF)
    contentType := resp.Header.Get("Content-Type")
    if contentType == "application/json" {
        var hosted HostedPDF
        if err := json.NewDecoder(resp.Body).Decode(&hosted); err != nil {
            return nil, nil, err
        }
        return nil, &hosted, nil
    }

    // Binary PDF response
    pdfBytes, err := io.ReadAll(resp.Body)
    return pdfBytes, nil, err
}

// MergePDFs merges multiple PDF files
func (c *Client) MergePDFs(pdfPaths []string, opts *Options) ([]byte, *HostedPDF, error) {
    body := &bytes.Buffer{}
    writer := multipart.NewWriter(body)

    for _, path := range pdfPaths {
        file, err := os.Open(path)
        if err != nil {
            return nil, nil, err
        }
        defer file.Close()

        part, err := writer.CreateFormFile("files", filepath.Base(path))
        if err != nil {
            return nil, nil, err
        }
        io.Copy(part, file)
    }

    if opts != nil {
        optionsJSON, _ := json.Marshal(opts)
        writer.WriteField("options", string(optionsJSON))
    }

    writer.Close()

    req, err := http.NewRequest("POST", c.BaseURL+"/pdf/merge", body)
    if err != nil {
        return nil, nil, err
    }

    req.Header.Set("X-API-Key", c.APIKey)
    req.Header.Set("Content-Type", writer.FormDataContentType())

    resp, err := c.HTTP.Do(req)
    if err != nil {
        return nil, nil, err
    }
    defer resp.Body.Close()

    if resp.StatusCode >= 400 {
        bodyBytes, _ := io.ReadAll(resp.Body)
        return nil, nil, fmt.Errorf("API error: %s", string(bodyBytes))
    }

    contentType := resp.Header.Get("Content-Type")
    if contentType == "application/json" {
        var hosted HostedPDF
        json.NewDecoder(resp.Body).Decode(&hosted)
        return nil, &hosted, nil
    }

    pdfBytes, _ := io.ReadAll(resp.Body)
    return pdfBytes, nil, nil
}

// Usage example in main.go:
// 
// client := syntaxdoc.NewClient("YOUR_API_KEY")
// 
// // Simple HTML to PDF
// pdf, _, err := client.GeneratePDF("<h1>Hello</h1>", &syntaxdoc.Options{
//     FileName: "hello",
//     Format:   "A4",
// })
// os.WriteFile("hello.pdf", pdf, 0644)
// 
// // Hosted PDF
// _, hosted, _ := client.GeneratePDF("<h1>Hosted</h1>", &syntaxdoc.Options{Host: true})
// fmt.Println("URL:", hosted.URL)
require 'net/http'
require 'json'

# SyntaxDoc API Client
class SyntaxDocClient
  attr_accessor :api_key, :base_url

  def initialize(api_key, base_url = 'https://api.syntaxdoc.com')
    @api_key = api_key
    @base_url = base_url
  end

  # Generate a PDF from HTML content
  def generate_pdf(html_content, options = {})
    options = {
      fileName: 'document',
      format: 'A4'
    }.merge(options)

    uri = URI("#{@base_url}/pdf/generate")
    request = Net::HTTP::Post.new(uri)
    request['X-API-Key'] = @api_key

    form_data = [
      ['files', html_content, { filename: 'index.html', content_type: 'text/html' }],
      ['options', options.to_json]
    ]
    request.set_form(form_data, 'multipart/form-data')

    response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end

    raise "API Error: #{response.body}" unless response.is_a?(Net::HTTPSuccess)

    if response['content-type']&.include?('application/json')
      JSON.parse(response.body)
    else
      response.body
    end
  end

  # Merge multiple PDF files
  def merge_pdfs(pdf_paths, options = {})
    uri = URI("#{@base_url}/pdf/merge")
    request = Net::HTTP::Post.new(uri)
    request['X-API-Key'] = @api_key

    form_data = pdf_paths.map do |path|
      ['files', File.open(path, 'rb'), { filename: File.basename(path), content_type: 'application/pdf' }]
    end
    form_data << ['options', options.to_json]
    request.set_form(form_data, 'multipart/form-data')

    response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end

    raise "API Error: #{response.body}" unless response.is_a?(Net::HTTPSuccess)

    if response['content-type']&.include?('application/json')
      JSON.parse(response.body)
    else
      response.body
    end
  end
end

# Usage example
client = SyntaxDocClient.new('YOUR_API_KEY')

# Simple HTML to PDF
pdf = client.generate_pdf('<h1>Hello World</h1>', fileName: 'hello', format: 'A4')
File.binwrite('hello.pdf', pdf)

# Host the PDF
result = client.generate_pdf('<h1>Hosted</h1>', host: true)
puts "PDF URL: #{result['url']}"

Framework Integration

Next.js API Route

// app/api/generate-pdf/route.ts
import { NextRequest, NextResponse } from 'next/server';

export async function POST(request: NextRequest) {
  const { html, options } = await request.json();
  
  const formData = new FormData();
  formData.append('files', new Blob([html], { type: 'text/html' }), 'index.html');
  formData.append('options', JSON.stringify(options));

  const response = await fetch('https://api.syntaxdoc.com/pdf/generate', {
    method: 'POST',
    headers: { 'X-API-Key': process.env.SYNTAXDOC_API_KEY! },
    body: formData,
  });

  if (!response.ok) {
    return NextResponse.json({ error: 'PDF generation failed' }, { status: 500 });
  }

  const pdf = await response.arrayBuffer();
  
  return new NextResponse(pdf, {
    headers: {
      'Content-Type': 'application/pdf',
      'Content-Disposition': `attachment; filename="${options.fileName || 'document'}.pdf"`,
    },
  });
}

Express.js Middleware

// middleware/pdfGenerator.js
const generatePdf = async (req, res, next) => {
  const html = req.body.html || req.html;
  if (!html) return next();

  const formData = new FormData();
  formData.append('files', new Blob([html], { type: 'text/html' }), 'index.html');
  formData.append('options', JSON.stringify(req.body.options || {}));

  try {
    const response = await fetch('https://api.syntaxdoc.com/pdf/generate', {
      method: 'POST',
      headers: { 'X-API-Key': process.env.SYNTAXDOC_API_KEY },
      body: formData,
    });

    if (!response.ok) {
      throw new Error('PDF generation failed');
    }

    req.pdf = await response.arrayBuffer();
    next();
  } catch (error) {
    next(error);
  }
};

module.exports = { generatePdf };

Django View

# views.py
from django.http import HttpResponse, JsonResponse
from django.views import View
import requests
import json

class GeneratePDFView(View):
    def post(self, request):
        html = request.POST.get('html', request.body.decode('utf-8'))
        options = json.loads(request.POST.get('options', '{}'))
        
        files = [('files', ('index.html', html, 'text/html'))]
        data = {'options': json.dumps(options)}
        
        response = requests.post(
            'https://api.syntaxdoc.com/pdf/generate',
            headers={'X-API-Key': settings.SYNTAXDOC_API_KEY},
            files=files,
            data=data
        )
        
        if not response.ok:
            return JsonResponse({'error': 'PDF generation failed'}, status=500)
        
        return HttpResponse(
            response.content,
            content_type='application/pdf',
            headers={'Content-Disposition': f'attachment; filename="{options.get("fileName", "document")}.pdf"'}
        )

Coming Soon

Official Node.js SDK

npm install @syntaxdoc/node - Full TypeScript support

Official Python SDK

pip install syntaxdoc - Async support included

Official PHP SDK

composer require syntaxdoc/php

Want to contribute? We're looking for community SDK maintainers for Java, .NET, Rust, and other languages. Reach out on GitHub!

On this page