# Projects

Inspect your DevMotion projects and their video exports. You can also render a project directly via `POST /renders` by passing its `project_id`.

> Access control: you can read your own projects. Public projects can be read by anyone with the project ID.

## GET /projects

Get all projects for the authenticated user.

Request

    curl https://devmotion.app/api/v1/projects \
      -H "Authorization: Bearer dm_live_YOUR_API_KEY"

### Response

GET /projects — response

    {
      "data": [
        {
          "id": "random_id",
          "name": "Random Project",
          "createdAt": "2026-02-14T13:25:27.369Z"
        },
        {
          "id": "another_random_id",
          "name": "Another Random Project",
          "createdAt": "2026-02-17T21:53:03.245Z"
        },
        ...
      ]
    }

## GET /projects/:id

Get a project’s metadata and layer structure.

Request

    curl https://devmotion.app/api/v1/projects/my_project_id \
      -H "Authorization: Bearer dm_live_YOUR_API_KEY"

### Response

GET /projects/:id — response

    {
      "id": "my_project_id",
      "name": "TikTok Intro",
      "is_public": true,
      "thumbnail_url": "https://storage.../thumb.jpg",
      "width": 1080,
      "height": 1920,
      "duration": 5,
      "fps": 30,
      "background": { "type": "solid", "color": "#0a0a0a" },
      "layers": [
        {
          "id": "layer_abc",
          "name": "Title",
          "type": "text",
          "visible": true,
          "locked": false,
          "props": { "content": "Hello World", "fontSize": 64 },
          "transform": { "position": { "x": 0, "y": -200 } },
          "style": { "opacity": 1 },
          "enter_time": 0,
          "exit_time": 5,
          "keyframes_count": 2
        }
      ]
    }

## POST /projects/:id/actions/:actionId

Run a media action on a layer within a project. Available actions: `generate-captions`, `dub-audio`, `extract-audio`.

Request — generate captions

    curl -X POST https://devmotion.app/api/v1/projects/my_project_id/actions/generate-captions \
      -H "Authorization: Bearer dm_live_YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{ "layerId": "video_layer_id", "language": "en" }'

Request — dub audio

    curl -X POST https://devmotion.app/api/v1/projects/my_project_id/actions/dub-audio \
      -H "Authorization: Bearer dm_live_YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{ "layerId": "audio_layer_id", "targetLang": "es" }'

Request — extract audio

    curl -X POST https://devmotion.app/api/v1/projects/my_project_id/actions/extract-audio \
      -H "Authorization: Bearer dm_live_YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{ "layerId": "video_layer_id" }'

### Action Parameters

Action | Required Fields | Optional Fields
--- | --- | ---
`generate-captions` | `layerId` | `language`, `prompt`
`dub-audio` | `layerId`, `targetLang` | `sourceLang`
`extract-audio` | `layerId` | —

### Response

POST /projects/:id/actions/:actionId — response

    {
      "action": "generate-captions",
      "layers_added": [
        { "id": "layer_xyz", "name": "Captions", "type": "captions" }
      ],
      "layers_updated": ["video_layer_id"]
    }

Returns `402` if the user’s plan requires an upgrade for the action.

## GET /projects/:id/exports

List video exports generated for a project.

Request

    curl https://devmotion.app/api/v1/projects/my_project_id/exports \
      -H "Authorization: Bearer dm_live_YOUR_API_KEY"

### Response

GET /projects/:id/exports — response

    {
      "data": [
        {
          "id": "export_xyz",
          "project_id": "my_project_id",
          "render_id": "render_abc123",
          "url": "https://storage.../video.mp4",
          "storage_key": "media/user_id/video.mp4",
          "file_size_bytes": 2456789,
          "duration_ms": 5000,
          "width": 1080,
          "height": 1920,
          "fps": 30,
          "version": 1,
          "created_at": "2025-01-15T10:30:15Z"
        }
      ]
    }