HTTP API

The file service the CLI, the connector and the server on your machine call. Trade an API token for a session, then call it with that.

Base URL
fffs.freakingfast.io
Requests
POST, JSON
Spec
OpenAPI 3.1

Authenticate#

An API token doesn't call the file service itself. Trade it at /exchange-token for a session token, and send that as the bearer token, along with X-Absurd-App: fffd.

Trade a token
curl -X POST https://auth.freakingfast.io/exchange-token \
  -H "Authorization: Bearer $FREAKING_FAST_API_TOKEN"
Answer
{
  "gelToken": "eyJhbGciOiJIUzI1NiIs…",
  "expiresIn": 86400,
  "userId": "73ad9b0e-7227-11ef-9399-bfdd82c9e268"
}

The session lasts a day, as expiresIn says in seconds. Trade the token again before it runs out. Keep userId: new files go under users/{userId}/.

Then call the service
curl -X POST https://fffs.freakingfast.io/search-files \
  -H "Authorization: Bearer $SESSION" \
  -H "X-Absurd-App: fffd" \
  -H "Content-Type: application/json" \
  -d '{ "text": "harbor", "type": "Video" }'

Upload a file#

Files go straight to storage on a signed form, so an upload never passes through the API.

  1. Ask for a form

    POST/generate-file-urls

    typestringrequired
    The kind of file, like Video, Audio or Image.
    fileNamestringrequired
    The name it shows under.
    fileSizeintegerrequired
    Its exact size in bytes, up to 2 TB.
    objectKeystringrequired
    Where it is stored: users/{userId}/…
    mimeTypestring
    Its content type.

    You get an uploadUrl and an uploadForm. The form lasts 2 days.

  2. Send the file

    POST the file to uploadUrl as multipart/form-data, with every uploadForm field before it, unchanged.

  3. Record it

    POST/insert-file

    Send the same fields with isPublic: false and creator: { id: userId }. The service reads the stored size back, and turns the file down if it differs from fileSize. You get the new file's id.

Large files#

Above 64 MiB, send a file in parts instead, many at once. If an upload stops, start it again with the same objectKey and only the missing parts go up.

CallDoes
/create-multipart-uploadOpens the upload, or picks up the one already open under that key.
/sign-upload-partsGives an upload URL for each part you ask for.
/complete-multipart-uploadJoins the parts into the file.
/insert-fileRecords it, as for any upload.

Share and download#

/generate-download-url gives a link to any of your files that lasts 6 hours. /toggle-file-access makes a file public, and its link then stays up for good, played from the closest region.

Work on files#

A job works on your files where they're stored, so nothing is downloaded to do it. Name its type, the files in order, each once, and its settings. What it makes lands as new files beside the first one (a folder's zip beside the folder), or in the folder you name, never over them.

Cut a clip
curl -X POST https://fffs.freakingfast.io/create-file-job \
  -H "Authorization: Bearer $SESSION" \
  -H "X-Absurd-App: fffd" \
  -H "Content-Type: application/json" \
  -d '{ "jobType": "cut", "fileIds": ["4f7c…"], "options": { "start": "1:20", "end": "2:05" } }'

It waits its turn, usually starting within half a minute when nothing's ahead of it. Ask /select-file-jobs how it's going, or watch /select-drive-events for its job event. Jobs count against your plan by the time they take: 1 hour a month on Intro, 4 hours a month on Basic, 15 hours a month on Pro. One that fails costs nothing, and /cancel-file-job stops one, keeping what it made. Send dryRun: true to check its settings and how long it should take without starting it.

TypeTakesSettings
cutA video or audioSettingsstart, end; exact for a frame-exact start; fadeIn, fadeOut for audio
proxyVideosSettingsheight: 720 or 1080
convertVideos, audio or picturesSettingsformat; codec h264 or hevc for video; maxEdge for pictures
shrinkA videoSettingstargetMB
reframeVideosSettingsaspect 9:16, 1:1, 4:5 or 16:9; rotate 90, 180 or 270
gifA videoSettingsstart, length up to 15 seconds, width, fps
burnInA videoSettingstimecode, captions, text
join2 to 50 videos, or audioSettingsformat, for audio
stillsA videoSettingsat, a list of moments, or every so many seconds
contactSheetA video, or picturesSettingscount for a video; columns
extractAudioVideosSettingsformat: mp3, m4a, wav or flac
loudnessVideos or audioSettingstarget: −14, −16 or −23 LUFS
splitAn audio fileSettingssilence in seconds, threshold in dB
stripMetadataPictures, videos or audioSettings–
watermarkPicturesSettingstext, position, opacity
makePdfPicturesSettingspageSize fit, a4 or letter; name
mergePdf2 to 50 PDFsSettingsname
splitPdfA PDFSettingsevery so many pages
extractPagesA PDFSettingspages, like 1-3,7
compressPdfPDFsSettingsquality: screen, ebook or printer
pdfToImagesA PDFSettingsformat jpg or png; dpi; pages
zipFiles, or a folderSettingsname
unzipA .zipSettings–
captionsVideos or audio, read firstSettingsformat: srt, vtt or txt
checksumAny filesSettingsalgorithm: sha256 or md5

Times are seconds, or a clock like 4:10. The OpenAPI spec has each setting's range.

Endpoints#

Every route is a POST to https://fffs.freakingfast.io with a JSON body. The OpenAPI spec has the full request and response for each.

Upload#

RouteDoes
/generate-file-urlsA signed form to upload a new file with.
/insert-fileRecord an uploaded file on the account.
/create-multipart-uploadStart an upload in parts, or resume the one open under this key.
/sign-upload-partsUpload URLs for parts of an open upload.
/complete-multipart-uploadJoin the parts into the finished file.
/abort-multipart-uploadThrow away an open upload and its parts.
/import-from-urlBring in a file from a link, fetched by the service.

Find and read#

RouteDoes
/select-user-filesEvery file you made.
/search-filesFind files by words, type, tag, folder, date, length, size, tempo, key or place, and folders by name.
/read-fileWhat is in a file, for a model: an image, a frame, a PDF’s or text file’s text.
/generate-download-urlA link to a file that lasts 6 hours.
/get-user-storage-usageBytes and files by bucket and kind.

Organize#

RouteDoes
/tag-filesTag files by name, making new tags as needed.
/update-file-tagsAdd one tag to files, or take it off.
/move-filesPut files in a folder, by path or id.
/update-file-descriptionSet a file’s description.
/toggle-file-accessMake a file public or private.
/select-collectionsYour folders, playlists, galleries and tags.

Playlists and galleries#

RouteDoes
/create-playlistA playlist of audio and video, in order.
/add-to-playlistAdd to the end of a playlist.
/reorder-playlistPut a playlist in a new order.
/create-galleryA gallery of images, in order.
/add-to-galleryAdd to the end of a gallery.
/reorder-galleryPut a gallery in a new order, and choose what goes up front.
/set-coverPut an image on a track or playlist as its art.
/set-video-thumbnailSet a video’s poster from a frame or an image.
/create-archive-requestA ZIP of files, a gallery or a playlist.

Requests and reviews#

RouteDoes
/create-file-requestA link anyone can send files to.
/select-file-requestsYour requests, and what arrived on each.
/set-file-request-openClose a request, or open it again.
/create-file-reviewA link to watch a video or track and leave notes on it.
/select-file-reviewsYour reviews, each with its notes as an edit list.
/reply-to-review-noteAnswer a note.
/set-review-note-resolvedMark a note dealt with, or not.

Activity#

RouteDoes
/select-file-viewsHow often other people opened your files, and who.
/select-drive-eventsWhat happened in your drive after a point, oldest first.

Images#

RouteDoes
/generate-imageStart an image from a prompt, on your plan.
/select-generationsHow your generations are going, and what they made.

Jobs#

RouteDoes
/create-file-jobWork on files where they are stored: cut, convert, zip and the rest.
/select-file-jobsYour jobs, newest first, with how far each has got and what it made.
/cancel-file-jobStop a job, keeping what it already made.

Trash#

RouteDoes
/trash-filesMove files to the trash.
/restore-filesBring files back.
/select-trashed-filesWhat is in the trash.
/purge-trashed-filesEmpty the trash, for good.
/delete-filesDelete files and what is stored for them, for good.

Errors#

Errors come back with a sentence for people and a code for code. retryable says whether trying again could work, which the status alone doesn't tell you.

400
{
  "error": "A fileSize is required",
  "code": "missing_field",
  "field": "fileSize",
  "retryable": false
}
StatusMeans
400Something in the request is missing or wrong. field names it.
401No session, or one that has expired. Trade the token again.
403Signed in, but not allowed, or the account has no plan.
404Nothing of yours has that id.
500Something went wrong on our side. retryable is true.