API Reference

State Endpoints

Manage poster state: validate structure, encode to shareable URLs, and decode URLs back to state.

Validate State

POST/api/v1/state/validate

Validate a LayerShareState structure before encoding or rendering. Returns detailed error messages.

Request Body

ParameterTypeDescription
(body)requiredLayerShareStateRequest body is the LayerShareState to validate directly (no wrapper needed)
request.json
{
  "canvas": {
    "aspectRatio": "9:16",
    "backgroundColor": "#1a1a1a"
  },
  "layers": [
    {
      "id": "bg",
      "name": "Background",
      "type": "background",
      "visible": true,
      "locked": false,
      "transform": {
        "x": 0,
        "y": 0,
        "width": 1,
        "height": 1,
        "rotation": 0,
        "opacity": 1
      },
      "contentType": "solid",
      "fill": {
        "type": "radial",
        "center": { "x": 0.4, "y": 0.35 },
        "radius": 0.95,
        "stops": [
          { "color": "#f8fafc", "opacity": 1, "position": 0 },
          { "color": "#0f172a", "opacity": 1, "position": 1 }
        ]
      },
      "solidColor": "#f8fafc"
    },
    {
      "id": "text-1",
      "name": "Title",
      "type": "text",
      "visible": true,
      "locked": false,
      "transform": {
        "x": 0,
        "y": 0,
        "width": 1,
        "height": 1,
        "rotation": 0,
        "opacity": 1
      },
      "content": "Hello World",
      "fontFamily": "DM Sans",
      "fontSize": 48,
      "fontWeight": "bold",
      "color": "#ffffff",
      "textAlign": "center",
      "letterSpacing": 0,
      "lineHeight": 1.2
    }
  ],
  "effect": {
    "effectId": "ascii-standard",
    "enabled": true,
    "ascii": {
      "style": "standard",
      "cellSize": 8,
      "invert": false,
      "color": true
    }
  }
}

Response (Valid)

response.json
{
  "valid": true
}

Response (Invalid)

error.json
{
  "valid": false,
  "errors": [
    "canvas.aspectRatio: must be one of 4:3, 3:4, 16:9, 9:16, 1:1, full",
    "layers[0].transform: transform is required and must be an object",
    "effect.effectId: \"invalid-effect\" is not a valid effect ID"
  ]
}

Required Layer Fields

Every layer must have these base fields:

FieldTypeDescription
idstringUnique identifier for the layer
namestringDisplay name in layers panel
typestringLayer type (text, image, video, 3d, background, etc.)
visiblebooleanWhether layer is visible
lockedbooleanWhether layer is locked for editing
transformobjectPosition, size, rotation, opacity

Encode State to URL

POST/api/v1/state/encode

Convert a LayerShareState to a shareable URL. URLs are automatically compressed when over 2000 characters.

Request Body

ParameterTypeDescription
staterequiredLayerShareStateThe poster state to encode
baseUrlstringBase URL for the shareable linkDefault: https://efecto.app
request.json
{
  "state": {
    "canvas": {
      "aspectRatio": "9:16",
      "backgroundColor": "#1a1a1a"
    },
    "layers": [
      {
        "id": "bg",
        "name": "Background",
        "type": "background",
        "visible": true,
        "locked": false,
        "transform": { "x": 0, "y": 0, "width": 1, "height": 1, "rotation": 0, "opacity": 1 },
        "contentType": "image",
        "fill": { "type": "solid", "color": "#1a1a1a", "opacity": 1 },
        "solidColor": "#1a1a1a",
        "inputMedia": {
          "mediaUrl": "https://images.unsplash.com/photo-1234",
          "mediaType": "image",
          "brightness": 1,
          "contrast": 1,
          "saturation": 1,
          "objectFit": "cover"
        }
      },
      {
        "id": "text-1",
        "name": "Title",
        "type": "text",
        "visible": true,
        "locked": false,
        "transform": { "x": 0, "y": -0.3, "width": 0.8, "height": 0.2, "rotation": 0, "opacity": 1 },
        "content": "EFECTO",
        "fontFamily": "DM Sans",
        "fontSize": 72,
        "fontWeight": "bold",
        "color": "#ffffff",
        "textAlign": "center",
        "letterSpacing": 0,
        "lineHeight": 1.2
      }
    ],
    "effect": {
      "effectId": "dither-floyd-steinberg",
      "enabled": true,
      "dither": {
        "pattern": "floydSteinberg",
        "pixelation": 3,
        "colors": ["#000000", "#ffffff"],
        "brightness": 1,
        "contrast": 1.2
      }
    },
    "postProcesses": [
      {
        "id": "pp-1",
        "type": "scanlines",
        "enabled": true,
        "settings": { "intensity": 0.3, "count": 200 }
      }
    ]
  },
  "baseUrl": "https://efecto.app"
}

Response

response.json
{
  "url": "https://efecto.app/canvas?lm=1&ca=16:9&cbg=%231a1a1a&...",
  "params": "lm=1&ca=16:9&cbg=%231a1a1a&..."
}

URL compression

Large states are automatically compressed. URLs over 2000 characters use pako compression, indicated by the lz=1 parameter.

Decode URL to State

POST/api/v1/state/decode

Convert a shareable URL back to LayerShareState. Supports both layer-mode and legacy URLs.

Request Body

ParameterTypeDescription
urlrequiredstringThe Efecto URL to decode
request.json
{
  "url": "https://efecto.app/canvas?lm=1&ca=16:9&cbg=%231a1a1a&..."
}

Response

response.json
{
  "mode": "layer",
  "state": {
    "canvas": {
      "aspectRatio": "16:9",
      "backgroundColor": "#1a1a1a"
    },
    "layers": [...]
  }
}

URL Modes

The mode field indicates the URL format:

  • layer - Modern LayerAppState format (supports all layer types)
  • legacy - Legacy AppState format (single model mode)

Get JSON Schema

GET/api/v1/schema

Get the JSON Schema for LayerAppState and layer types.

Query Parameters

ParameterTypeDescription
typestringFilter by layer type (text, image, video, 3d, shape, background, group)

Response

response.json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "LayerAppState",
  "type": "object",
  "required": ["canvas", "layers"],
  "properties": {
    "canvas": {
      "type": "object",
      "required": ["aspectRatio", "backgroundColor"],
      "properties": {
        "aspectRatio": {
          "type": "string",
          "enum": ["4:3", "3:4", "16:9", "9:16", "1:1", "full"]
        },
        "backgroundColor": { "type": "string", "pattern": "^#[0-9a-fA-F]{6}$" }
      }
    },
    "layers": {
      "type": "array",
      "items": { "$ref": "#/$defs/Layer" }
    }
  }
}

Available Types

  • /api/v1/schema - Full LayerAppState schema
  • /api/v1/schema?type=text - TextLayer schema
  • /api/v1/schema?type=image - ImageLayer schema
  • /api/v1/schema?type=video - VideoLayer schema
  • /api/v1/schema?type=3d - Layer3D schema
  • /api/v1/schema?type=shape - ShapeLayer schema
  • /api/v1/schema?type=background - BackgroundLayer schema
  • /api/v1/schema?type=group - GroupLayer schema

Technical Notes

The API uses LayerShareState - the canonical format for sharing and API operations.

Required Fields

  • canvas.aspectRatio - one of: 4:3, 3:4, 16:9, 9:16, 1:1, full
  • canvas.backgroundColor - hex color string (e.g., "#1a1a1a")
  • Each layer needs: id, name, type, visible, locked, transform
  • Background layer should be at index 0
  • effect (optional): effectId, enabled, plus effect-specific settings
  • postProcesses (optional): array of post-process instances