Logo DanimDanim API Docs

Introduction

From the creation of personalized videos for your users and clients to the large-scale marketing campaign, our API is an easy way to achieve your goals with automated video creation.

The Danim API is an interface for reading and writing data from and to client online accounts, organizations that holds them, videos having been or being generated, and so on.
The web API URLs follow the following forms:
  • https://api.danim.com/write/{DOMAIN}/{COMMAND} for writes
  • https://api.danim.com/read/{DOMAIN}/{QUERY} for reads
Please note that Danim API is not a REST API, hence all requests are passed through POST method (you’ll not see methods such as DELETE, PATCH, PUT, etc.). Our read API is built with GraphQL and GraphiQL is available in this documentation to visually explore our read API.

Want to try our API?

Please contact us if you have any question or feature request!

Content-Type

When requesting via HTTP POST, you may present your arguments as either standard application/x-www-form-urlencoded POST parameters in your Content-Type header or use JSON application/json instead.

Note that when dealing with file(s) upload, you’ll will not be able to use application/x-www-form-urlencoded, but be compelled to use multipart/form-data instead. If you really want to avoid the multipart form when providing files, or for any other reason, you can provide them with URLs (of your own cloud, for instance) or preloaded-file IDs. You'll find more informations about that in the dedicated section.

Warning

When using Content-Type: multipart/form-data, don’t forget to provide the boundary (see details here). Some tools automatically calculate it (e.g. common browsers, Postman, etc.), but you could also provide an empty Content-Type header, and we’ll guess what you meant by this.

URL-encoded bodies

When sending URL-encoded data, set your HTTP Content-Type header to application/x-www-form-urlencodedand present your key/value pairs according to RFC-3986. For example, a video generation might look something like this:

-> POST /write/workspace/create
–––––
Authorization: ...
Content-Type: x-www-form-urlencoded
–––––
name=My+workspace&description=My+workspace+description
JSON-encoded bodies
But you may alternatively send your HTTP POST data with header Content-Type: application/json.

There are some ground rules:
  • you must explicitly set the Content-Type HTTP header to application/json. We won’t interpret your POST body as such without it.
  • you cannot send your credentials as an attribute in your posted JSON.
  • do not mix arguments up, between URL-encoded and JSON attributes. Choose one approach per request.
  • providing an explicitly null value for an attribute will result in whichever default behavior is assigned to it.
For example, to send the same request than above with a JSON POST body:
-> POST /write/workspace/create
–––––
Authorization: ...
Content-Type: application/json
–––––
{
    "name": "My workspace",
    "description": "My workspace description"
}
Errors specific to JSON

If the posted JSON is invalid, you’ll receive one of the following errors (meta.type) in response (see response details below): In all cases, you’ll need to revise your JSON or how you’re transmitting your data to resolve the error condition.

In all cases, you’ll need to revise your JSON or how you’re transmitting your data to resolve the error condition.
NameDescription
InvalidJsonThe JSON POST body cannot be parsed. This might be because it’s actually not JSON, or perhaps you did not correctly set your HTTP Content-Type header. Also make sure your JSON attribute keys are strings wrapped with double-quote characters.
MalformedUtf8CharactersWe understood that your code was JSON-like enough to parse it, but some character may have been incorrectly encoded.

Evaluating responses

Each web API response contains a JSON object, which will always contain a top-level boolean property success, indicating success or failure. The response code will always be 200.

Warning

Do not forget to include treatment in your code for 40x and 50x responses, which like in all online protagonists could potentially occur.

For success results, the data object property will contain useful pieces of information, such as the ID of a newly created entity, for example. Its internal fields are completely dependant on the endpoint. It is highly recommended that you log the meta.warnings on your side, to be alerted in real-time of any potential issues and deprecations.

<- 200–––––
{
    "success": true,
    "data": {
        "here_is": "some_useful_information",
        "dedicated": "to_this_precise_endpoint"
    },
    "meta": {
        "warnings": [
            "First warning: beware on deprecation blablabla",
            "Second warning: the data you see in data.here_is is blablabla"
        ]
    }
}

For failure results, the message property will contain a detailed and verbose description of what had failed, and why, and how. There also will be a short machine-readable error code, found under meta.type, to get a more generic and clean way of dealing with errors (since this will be much more static in the course of time).

<- 200–––––
{
    "success": false,
    "message": "Something dreadful occured when trying to generate video 5216c289-96d8-4124-bcf8-a70b7e688e97, it’s a complete shambles!",
    "meta": {
        "type": "VideoGenerationFailed"
    }
}

Rate limits

Be aware of the fact that the amount of requests you may perform is limited in time (based upon your API credentials), with a precise per-minute quota.
This amount may be discussed, feel free to contact us.

If your request is overflowing the quota, you’ll get a failure (success: false) with meta.type: RateLimitExceeded(see response details above).


Authentication

We provide you app credentials, which consist of two keys, a public ID and a private secret. You must keep the secret out of sight. Go to API settings to get your credentials: app.danim.com/organization/api

Credentials
You have 3 ways to provide them in each request:
  • Extra non-standard X-foo-bar headers, the request containing two headers in the form of X-App-Id: <ID> and X-App-Secret: <secret>.
  • Basic HTTP authentication, the request containing a header in the form ofAuthorization: Basic <credentials>, where credentials is the Base64 encoding of <ID>:<secret>(ID and secret joined by a single colon ":", see RFC 7617).
  • Query parameters, in the form ofappId=<ID> and appSecret=<secret>.
Related errors
NameDescription
AuthenticationRequiredMissing app ID
AppDoesNotExistThe app does not exist
InvalidAppSecretThe provided app secret is not correct
Examples
Basic HTTP authentication

-> POST /write/video/create
–––––
Authorization: Basic base64encode(26rth97x368jj78n8nk3l4m:67t667thht7fwffhdullfuuejeh78ijjjf883zz2hhh34f)
Extra headers

-> POST /write/video/create
–––––
X-App-Id: 26rth97x368jj78n8nk3l4m
X-App-Secret: 67t667thht7fwffhdullfuuejeh78ijjjf883zz2hhh34f
Query parameters

-> POST /write/video/create?appId=26rth97x368jj78n8nk3l4m&appSecret=67t667thht7fwffhdullfuuejeh78ijjjf883zz2hhh34f

File sending

We herein illustrate the possible methods for providing files via your POST request body.

Preloaded file
With this method, you use the endpoint /upload/me to send a file and get its ID in the response. You can use this ID later in another POST request.

See /upload/me dedicated section for more details.

⭐️ Best practice

We encourage the use of this method because it gives you the way to parallel loading on your frontend.

If you have numerous file inputs in your form, using this method will save you from very long browser submits.
I.e. you load a file when the user fills the form (once loaded, you store the ID), and on submit, you send the ID instead of the user binary. Our backend will immediately assign the related file (given its ID).

Please note that the preloaded-file ID will be available and valid for the next 24 hours, and will be expired afterwards.
Binary and Content-Type: multipart/form-data header
Binary example

-> POST /write/workspace/create
–––––
Authorization: ...
Content-Type: multipart/form-data; boundary=...
–––––
name: "My workspace"
logo: (binary)
Readable cloud URL
You could provide a remote file URL (of your own cloud, for instance), following the file+http(s):// format. For example, if you want to use the link https://my.cloud/path/file.jpg:
Readable cloud url example

-> POST /write/workspace/create
–––––
Authorization: ...
Content-Type: application/json
–––––
{
    "name": "My workspace",
    "logo": "file+https://my.cloud/path/file.jpg"
}

Why add file+?

Adding file+ to the scheme (http or https) is required, otherwise the field would be considered to be a mere string which should not be subject to any treatment, and would be understood as such. Please do not forget to send us the scheme, otherwise your url will not be accepted.
Related errors

You may receive one of the following errors (meta.type) in response:

NameDescription
FileCannotBeDownloadedImpossible to download a remote file given its URL
FileMimeTypeCannotBeGuessedFile has been downloaded given its URL, but no MIME type could have been deduced
FileExtensionCannotBeGuessedFile has been downloaded given its URL, but no extension could have been deduced
FileIsTooLargeFile size is too high
FileExtensionIsNotAcceptedFile extension is not authorized (in general, on the platform)
FileMimeTypeIsNotAcceptedFile MIME type is not authorized (in general, on the platform)
EmptyFileThe file has no content (size to 0)

API Reference

/upload/me
Upload a file

This endpoint lets you upload files to our platform, which you may reuse elsewhere using their IDs (e.g., in the POST body of another API call).

Request parameters
Method: POST
Content-Type: multipart/form-data

file *file

The file content

Response:success

{
  "success": true,
  "data": {
    "file": {
      "id": "d3f9c21c-9cb8-4f90-80b5-b87e1c951db3",
      "created_at": "2020-09-05T15:40:40+00:00",
      "original_name": "my-pic.jpeg",
      "mime_type": "image/jpeg",
      "size": 412941,
      "url": "https://s3.eu-west-3.amazonaws.com/com.danim.prod/app/api-app/file-store/68147b15-d6ee-4a2c-bfa0-57242c4d2d97.jpeg",
      "path": "app/api-app/file-store/68147b15-d6ee-4a2c-bfa0-57242c4d2d97.jpeg"
    }
  }
}
Response:error

{
  "success": false,
  "message": "File extension \"myself.gif\" is not accepted. You can choose among: jpg, jpeg, png.",
  "meta": {
    "type": "FileExtensionIsNotAccepted"
  }
}
Errors details

Error codeError description
UserNotFound

The user is not found.

CommandNotAuthorized

The command is blocked for you. This may have multiple possible reasons: payload content, API app rights, or even a bug... (feel free to contact us)

BadParameter

Bad parameter in the payload

MissingParameter

Missing parameter in the payload

FileExtensionIsNotAccepted

File extension is not authorized

FileIsTooLarge

File size is too high

FileMimeTypeIsNotAccepted

File MIME type not authorized

RateLimitExceeded

Rate limit exceeded. Contact us if you need more

EmptyFile

The file has no content (size to 0)

FileCannotBeDownloaded

File download failed

FileExtensionCannotBeGuessed

File downloaded, but no extension could have been deduced

FileMimeTypeCannotBeGuessed

File MIME type could not be guessed


/write/video/change
Change a video

This endpoint lets you change your video: name, description, etc.

Request parameters
Method: POST
Content-Type: application/json

video_id *string

The video ID


patch *object

This is an object holding all the wished changes. Each sub-param of the patch can be omitted if you do not want to change it: this is equivalent to provide the value "IGNORE" (from the ImperativeVerb enum).

namestring | IGNORE | null

Name of the video (title which often appears on snippets, pages, etc.)

Default: IGNORE
descriptionstring | IGNORE | null

Description of the video (used for social sharing, locally on the platform, etc.)

Default: IGNORE
Request example

{
  "video_id": "eeeca184-e92c-46cf-b1bb-36703e91d765",
  "patch": {
    "name": "Wonderful house",
    "description": "This video shows the rooms..."
  }
}
Response:success

{
  "success": true,
  "data": []
}
Response:error

{
  "success": false,
  "message": "Video with ID \"e7aacd22-24fc-46fc-9752-5a5571944836\" cannot be found.",
  "meta": {
    "type": "VideoNotFound"
  }
}
Errors details

Error codeError description
VideoNotFound

The video is not found.

CommandNotAuthorized

The command is blocked for you. This may have multiple possible reasons: payload content, API app rights, or even a bug... (feel free to contact us)

BadParameter

Bad parameter in the payload

MissingParameter

Missing parameter in the payload

ConfigThumbnailNotFound

The config thumbnail is not found.

StateChangeIsNotAuthorized

Changing video state from one to another is not authorized

FileIsTooLarge

File size is too high

FileMimeTypeIsNotAccepted

File MIME type not authorized

InvalidTemplateDataFileFormat

Invalid file in template data

InvalidTemplateDataFileMimeType

Invalid MIME type for file in template data

MissingTemplateDataComposition

A required template composition has not been provided in template_data, when it should have been

MissingTemplateDataInput

A required template input has not been provided in template_data, when it should have been

FileExtensionIsNotAccepted

File extension is not authorized

ApiAppVideoCannotBeLocal

Video made by an API app cannot be generated locally

InsufficientCreditsForGeneration

The organization has no sufficient credits for this video generation

InsufficientPlan

The organization plan does not allow your command. Please contact us if you think this is abnormal.

RateLimitExceeded

Rate limit exceeded. Contact us if you need more


/write/video/create
Create a video

This endpoint lets you create a video from scratch. You may choose to set it as draft, or directly launch it for generation.

Request parameters
Method: POST
Content-Type: application/json

template_idstring | null

ID of template from which the video must be generated

Default: null

template_datastring | object | null

Template data for generation (id/value pairs: see our guide). If there's no file (URL, ID, bin, etc.) in your data, you can provide a JSON-encoded string.

Default: true

descriptionstring | null

Description of the video

Default: null

namestring | null

Name of the video

Default: Generated (template name + ' #' + short ID)

workspace_idstring | null

Workspace in which the video should be created

Default: The one of the template (if it exists), or the first of its organization ones otherwise

callback_urlstring | null

This webhook URL will be solicited on video generation success. It will by default use the POST method (Content-Type being application/x-www-form-urlencoded), and provide the following parameters:

  • id (video ID)
  • raw_url (full resolution video URL)
  • raw_quicklook_url (GIF preview URL)
  • raw_thumbnail_url (main thumbnail URL)
  • player_url (video player URL)

If you prefer to get this stuff done via the GET method, add +get in your url scheme (e.g. https+get://my.app/webhook/1)

Default: null

stateDRAFT | PENDING_IN_APP | GUESS

State of video. E.g., DRAFT to create a video that will not be generated once created, and that you may generate afterward via /write/video/generate; PENDING_IN_APP to start right now (queuing).

Default: GUESS
Request example

{
  "template_id": "5958fb82-ef69-418f-abb1-5fa2ad355aaa",
  "template_data": {
    "text-1": "Alice's select value",
    "text-2": "Alice's text value",
    "image-1": "5c574215-5327-4d66-94b9-8f8b99720536"
  },
  "description": "Hi everyone, this video has an image! Alice.",
  "name": "Alice's video",
  "workspace_id": "36a167cf-8817-4f43-8b9d-9308ad25a8cc",
  "callback_url": "https://lustkcehiqywpfarnbzmvxgdjo.service.com/mock/path",
  "state": "GUESS"
}
Response:success

{
  "success": true,
  "data": {
    "id": "607e5f57-6e4f-4d28-bd81-377bb1a40de1",
    "short_id": "fg56h378k",
    "name": "Alice's video"
  }
}
Response:error

{
  "success": false,
  "message": "The input \"text-3\" is required but has not been provided",
  "meta": {
    "type": "MissingTemplateDataInput"
  }
}
Errors details

Error codeError description
TemplateNotFound

The template is not found.

VideoAlreadyExists

Video already exists.

WorkspaceInconsistency

Inconsistency between workspaces.

WorkspaceNotFound

The workspace is not found.

WorkspaceMustBeSet

A workspace ID must be provided

CommandNotAuthorized

The command is blocked for you. This may have multiple possible reasons: payload content, API app rights, or even a bug... (feel free to contact us)

BadParameter

Bad parameter in the payload

MissingParameter

Missing parameter in the payload

RateLimitExceeded

Rate limit exceeded. Contact us if you need more

ConfigThumbnailNotFound

The config thumbnail is not found.

EitherTemplateXorTemplateSourceMustBeSet

Either template xor template source must be set

StateNotAuthorizedOnCreation

State not authorized on creation

FileIsTooLarge

File size is too high

FileMimeTypeIsNotAccepted

File MIME type not authorized

InvalidTemplateDataFileFormat

Invalid file in template data

InvalidTemplateDataFileMimeType

Invalid MIME type for file in template data

MissingTemplateDataComposition

A required template composition has not been provided in template_data, when it should have been

MissingTemplateDataInput

A required template input has not been provided in template_data, when it should have been

FileExtensionIsNotAccepted

File extension is not authorized

ImpossibleCompletion

Completion could not be made

InvalidCompletionUrl

Provided URL is not valid for completion.

InvalidHtmlCodeExtractedFromCompletionUrl

The HTML code extracted from the url is not valid for completion.

StateChangeIsNotAuthorized

Changing video state from one to another is not authorized

ApiAppVideoCannotBeLocal

Video made by an API app cannot be generated locally

InsufficientCreditsForGeneration

The organization has no sufficient credits for this video generation

InsufficientPlan

The organization plan does not allow your command. Please contact us if you think this is abnormal.

EmptyFile

The file has no content (size to 0)

FileCannotBeDownloaded

File download failed

FileExtensionCannotBeGuessed

File downloaded, but no extension could have been deduced

FileMimeTypeCannotBeGuessed

File MIME type could not be guessed

TemplateDataFileNotFound

One provided file ID has been provided but cannot be found in old previous data. E.g., a preloaded-file ID has been provided, but was expired, so that we try to find the ID in old data files, with no success)


/write/video/generate
Generate a video

This endpoint lets you launch video generation when this one is still a draft.

Request parameters
Method: POST
Content-Type: application/json

video_id *string

The video ID

Request example

{
  "video_id": "9eef0d8c-7ff2-4e9d-96a0-eb5a93f04bd4"
}
Response:success

{
  "success": true,
  "data": []
}
Response:error

{
  "success": false,
  "message": "Video with ID \"e7aacd22-24fc-46fc-9752-5a5571944836\" cannot be found.",
  "meta": {
    "type": "VideoNotFound"
  }
}
Errors details

Error codeError description
BotNotFound

The bot is not found.

CouldNotSendVideoGenerationSpecs

Could not send video generation specs to bot.

VideoNotFound

The video is not found.

MissingParameter

Missing parameter in the payload

CommandNotAuthorized

The command is blocked for you. This may have multiple possible reasons: payload content, API app rights, or even a bug... (feel free to contact us)

BadParameter

Bad parameter in the payload

StateChangeIsNotAuthorized

Changing video state from one to another is not authorized

FileIsTooLarge

File size is too high

FileMimeTypeIsNotAccepted

File MIME type not authorized

InvalidTemplateDataFileFormat

Invalid file in template data

InvalidTemplateDataFileMimeType

Invalid MIME type for file in template data

MissingTemplateDataComposition

A required template composition has not been provided in template_data, when it should have been

MissingTemplateDataInput

A required template input has not been provided in template_data, when it should have been

FileExtensionIsNotAccepted

File extension is not authorized

ApiAppVideoCannotBeLocal

Video made by an API app cannot be generated locally

InsufficientCreditsForGeneration

The organization has no sufficient credits for this video generation

InsufficientPlan

The organization plan does not allow your command. Please contact us if you think this is abnormal.

RateLimitExceeded

Rate limit exceeded. Contact us if you need more


/write/video/remove
Remove a video

This endpoint lets you remove one of your videos.

Request parameters
Method: POST
Content-Type: application/json

video_id *string

The video ID

Request example

{
  "video_id": "3947c1f6-fde1-490e-8320-6c2bcfc07f95"
}
Response:success

{
  "success": true,
  "data": []
}
Response:error

{
  "success": false,
  "message": "Video with ID \"e7aacd22-24fc-46fc-9752-5a5571944836\" cannot be found.",
  "meta": {
    "type": "VideoNotFound"
  }
}
Errors details

Error codeError description
VideoNotFound

The video is not found.

CommandNotAuthorized

The command is blocked for you. This may have multiple possible reasons: payload content, API app rights, or even a bug... (feel free to contact us)

BadParameter

Bad parameter in the payload

FileExtensionIsNotAccepted

File extension is not authorized

FileIsTooLarge

File size is too high

FileMimeTypeIsNotAccepted

File MIME type not authorized

MissingParameter

Missing parameter in the payload

RateLimitExceeded

Rate limit exceeded. Contact us if you need more


/read
All our read API is explorable with GraphiQL. You can navigate between several examples of queries by clicking on the buttons below the explorer. The GraphQL documentation adapts to your scopes, so don't be surprised if it changes in the Explorer after you fill in your App ID and App Secret.

Register your app credentials to start exploring our API.

Explorer
query
api
template
templates
video
videos
after:
createdAfter:
createdBefore:
first: $quantity
id:
inWorkspace:
name:
offset:
ofPublicTemplate:
ofTemplate:
shortId:
sort:
state: $state
count
edges
cursor
node
createdAt
description
file
id
name
minimalistic:
playerUrl
progress
quicklook
ratio
shortId
state
template
templateId
thumbnail
watermarked
workspace
workspaceId
pageInfo
totalCount
workspace
workspaces
Add new
GraphiQL
Query Variables
Examples:

Guides

You can find here multiple guides which will help you step by step in your use of Danim API
Read a template and create a video
Learn how to create a video
Read and understand details about a template

Each template has a different structure. You need to know which data is needed by Danim for each template, which fields are required or not, the ids of these fields, etc.
You can find these informations by two different ways:

Easy way: with danim.com

You can find out how to write your video creation request on each generation page by clicking on the "code" icon below the template thumbnail.

Hard way: with GraphQL
Get the id of your template, and use GraphQL to find the specs about it.
Get template specs by id - open in GraphiQL

query GetTemplateSpecsById($id: String = null) {
  template(id: $id) {
    specs
    inputs
  }
}

Warning

You have to parse specs in GraphQL response because this attribute is stringified.
Specs example

{
  "specs": {
    "info": {
      "ratios": [1, 1.78, 0.56],
      "theme": {
        "layout": {
            "main-color": {
                "name": "Main color"
            },
            "secondary-color": {
                "name": "Secondary color"
            },
            "text-color": {
                "name": "Text color"
            }
        },
        "variants": [
            {
                "name": "Main theme",
                "colors": {
                    "main-color": "#00aaa1",
                    "secondary-color": "#09121d",
                    "text-color": "#FFFFFF"
                }
            },
            {
                "name": "Alternative theme",
                "colors": {
                    "main-color": "#f1a649",
                    "secondary-color": "#3b24ab",
                    "text-color": "#FFFFFF"
                }
            }
        ]
      }
    },
    "compositions": [
      {
        "id": "01-intro",
        "description": "Introduction",
        "required": false,
        "texts": [
          {
            "id": "title",
            "description": "Film title",
            "required": true,
            "type": "text",
            "max_length": 30,
            "strict_check": false
          },
          {
            "id": "duration",
            "description": "Film duration",
            "required": false,
            "type": "number",
            "strict_check": true,
            "is_int": true,
            "min_numeric_value": 0,
            "suffix": "minutes"
          }
        ]
      },
      {
        "id": "02-review",
        "description": "Review",
        "required": true,
        "texts": [
          {
            "id": "score",
            "description": "Film score",
            "required": true,
            "type": "number",
            "strict_check": true,
            "is_int": false,
            "min_numeric_value": 0,
            "max_numeric_value": 5
          }
        ],
        "files": [
          {
            "id": "poster",
            "description": "Poster",
            "required": false,
            "type": "image",
            "min_width": 500,
            "min_height": 1200
          }
        ]
      },
      {
        "id": "03-casting",
        "description": "Casting",
        "required": false,
        "is_dynamic": true,
        "min_dynamic_zone_quantity": 0,
        "max_dynamic_zone_quantity": 5,
        "dynamic_zone_start": true,
        "texts": [
          {
            "id": "job",
            "description": "Job / Role",
            "required": false,
            "type": "text",
            "max_length": 20,
            "strict_check": false
          },
          {
            "id": "casting-name",
            "description": "Person name",
            "required": true,
            "type": "text",
            "max_length": 20,
            "strict_check": false
          }
        ],
        "files": [
          {
            "id": "bg-footage",
            "description": "Background image / video",
            "required": false,
            "type": "image_video",
            "min_width": 1080,
            "min_height": 1080,
            "duration_strategy": "variable",
            "min_duration": 4,
            "max_duration": 30,
            "force_muted": true
          }
        ]
      },
      {
        "id": "04-quote",
        "description": "Quote",
        "required": false,
        "is_dynamic": true,
        "dynamic_zone_end": true,
        "texts": [
          {
            "id": "quote-paragraph",
            "description": "Quote paragraph",
            "required": true,
            "type": "paragraph",
            "max_paragraph_line_length": 20,
            "max_paragraph_lines": 3,
            "strict_check": true
          }
        ]
      }
    ],
  },
  "inputs": [
    "title",
    "duration",
    "score",
    "poster",
    "job",
    "casting-name",
    "bg-footage",
    "quote-paragraph"
  ]
}

How to understand specs?
A template is an assembly of several compositions in which there are several inputs (texts and files). Each composition and each input has rules that define the expected data.
One of the most important rules for compositions, texts and files is required. In some cases, you can omit an input during the creation of a video and it will not be visible in the video. In other cases, you can't and an error will be thrown.

Here is a summary:
  • you didn’t provide any input (required or optional) of an optional composition: the composition itself will not appear in the video
  • you didn't provide the value of an optional input in a required (or optional) composition: its value will then be empty
  • you didn't provide the value of a required input in a required composition or in an optional composition from which you provided another input: an error will be thrown (see errors)
Other informations such as description, type, max_length, min_numeric_value, min_width (etc.) are easy to understand.
Please note that these rules are informative in most of the cases. For example, if you don't respect the rule max_length for a text input, no error is returned unless strict_check is TRUE. These are the rules affected by strict_check:
  • max_length
  • min_numeric_value
  • max_numeric_value
  • is_int
  • max_paragraph_line_length
  • max_paragraph_lines
  • values
There are two main families of inputs: texts and files. There are several types in each of them:
  • For texts: text, number, paragraph, select, boolean
  • For files: image, video, image_video
Create a video based on this template
File sending

We'll use the template specs above as an example. The field called poster is a file, so you have to choose between the several ways described in file sending section to send it.
We highly advise you to send your file(s) separately with /upload/me and get the file id in response with data.file.id.

Images have rules related to their dimensions: min_width, min_height, max_width, max_height.
These rules are informative, so if your image doesn't match the required dimensions, we'll automatically crop and resize it: no error will be thrown. You can ask us to crop these images by sending an additional crop object (see expert mode below).

Videos have rules related to their duration: duration_strategy ("fixed" or "variable"), duration, min_duration, max_duration. If duration_strategy is "fixed", video duration is defined by duration. If duration_strategy is "variable", video duration has to be defined between min_duration and max_duration.
As for images, these rules are informative, so if your video doesn't match the specified duration, we'll automatically cut it: no error will be thrown. You can ask us to cut these videos by sending an additional range array (see expert mode below).

Launch a new generation
Now that you get all the details needed to create a video, we can use the endpoint /write/video/create to launch a new generation.

template_data can have 2 different layouts depending on the features you want to use. A minimalist and easy to use mode allows you to create a video without having to set the ratio and the theme. In this mode, you can't duplicate the compositions or define custom crop and cut values for images and videos. All you have to do is to send a list of entries you want to see in your video.
Here are different scenarios based on the specs above. To simplify, template_data is the only displayed field, but other required fields have to be sent too:
Video with all fields - success

{
  "template_data": {
    "title": "A great movie",
    "duration": 112,
    "score": 4.8,
    "poster": "my-file-id"
  }
}

Minimal video without all the optional fields - success

{
  "template_data": {
    "score": 4.8
  }
}
In this example, the composition 01-intro will not be displayed in the generated video because all these inputs are missing in the request. The image poster will not be displayed and no error will be thrown because it's not a required field.
Missing inputs - error

{
  "template_data": {
    "duration": 112,
    "poster": "my-file-id"
  }
}
Here, two required fields are missing: title and score. Error MissingTemplateDataInput will be thrown.
Bad input value - error

{
  "template_data": {
    "title": "A great movie",
    "duration": 20.54,
    "score": -2,
    "poster": "my-file-id"
  }
}
In this last example, two fields have wrong values when strict_check is TRUE. duration is a float but it should be an integer, and score is less than 0 while min_numeric_value is 0. Error BadParameter will be thrown.

null, false, "" or undefined?

The easiest way to tell Danim to ignore an input is to not send this input in template_data. You can also send null, but if you send an empty string "" or false, the value of the input will be evaluated.
Get back video urls
If everything is fine with your template_data, you'll receive a similar response (with different ids):
/write/video/create Request

{
  "template_id": "your-template-id",
  "template_data": {
    "title": "A great movie",
    "duration": 112,
    "score": 4.8,
    "poster": "my-file-id"
  },
  "name": "My favorite film",
  "callback_url": "https://my.app/webhook"
}
Response - success

{
  "success": true,
  "data": {
    "id": "new-video-long-id",
    "short_id": "new-video-short-id",
    "name": "My favorite film"
  }
}
Be notified with a webhook
Once your video has been created, we'll notify you with a POST request (application/x-www-form-urlencoded) at your callback_url.
These attributes are sent: id, raw_url (full resolution video), raw_quicklook_url (GIF preview), raw_thumbnail_url (main thumbnail), and player_url.

This is a common use case of callback_url:
  • Save data.id from /write/video/create response in your database
  • When a request is received at your callback_url, find the related video in your database thanks to the id in POST parameters
  • You're now sure that this video has been created. You can save data sent by the webhook in your database, or get additional informations with another GraphQL request

Quick tip

During your tests with our API, we highly suggest that you use webhook.site to try the callback_url attribute.