API

Idempotent requests

Version 2026-11-01OpenAPI 3.1Download openapi.json

Retry a write without creating the same resource twice.

You will make POST retries safe after a connection drops or your application cannot tell whether a request completed. Generate one unique idempotency key for each logical operation.

Send a key

curl
response=$(curl --fail-with-body --request POST 'https://api.todayfiles.com/v1/videos' \
  --header "Authorization: Bearer $TODAYFILES_API_KEY" \
  --header 'Idempotency-Key: replace-with-a-unique-request-key' \
  --header 'Content-Type: application/json' \
  --data '{"title":"Launch trailer","source":{"type":"upload"}}')
printf '%s\n' "$response"
Node
const response = await fetch("https://api.todayfiles.com/v1/videos", {
  method: "POST",
  headers: {
    Authorization: "Bearer " + process.env.TODAYFILES_API_KEY,
    "Idempotency-Key": "replace-with-a-unique-request-key",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({"title":"Launch trailer","source":{"type":"upload"}}),
});
if (!response.ok) throw new Error(await response.text());
const result = response.status === 204 ? null : await response.json();
console.log(result);
Python
import json
import os
import requests

response = requests.request(
    "POST", "https://api.todayfiles.com/v1/videos",
    headers={
        "Authorization": "Bearer " + os.environ["TODAYFILES_API_KEY"],
        "Idempotency-Key": "replace-with-a-unique-request-key",
    },
    json=json.loads("{\"title\":\"Launch trailer\",\"source\":{\"type\":\"upload\"}}"),
    timeout=30,
)
response.raise_for_status()
print(response.json() if response.content else None)
PHP
<?php
$client = curl_init("https://api.todayfiles.com/v1/videos");
curl_setopt_array($client, [
    CURLOPT_CUSTOMREQUEST => "POST",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('TODAYFILES_API_KEY'),
        'Idempotency-Key: replace-with-a-unique-request-key',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => "{\"title\":\"Launch trailer\",\"source\":{\"type\":\"upload\"}}",
]);
$body = curl_exec($client);
if ($body === false) throw new RuntimeException(curl_error($client));
$status = curl_getinfo($client, CURLINFO_RESPONSE_CODE);
curl_close($client);
if ($status >= 400) throw new RuntimeException($body);
$result = $body === '' ? null : json_decode($body, true, 512, JSON_THROW_ON_ERROR);
print_r($result);
Go
package main

import (
    "encoding/json"
    "io"
    "net/http"
    "os"
    "strings"
    "time"
)

func main() {
    request, err := http.NewRequest("POST", "https://api.todayfiles.com/v1/videos", strings.NewReader("{\"title\":\"Launch trailer\",\"source\":{\"type\":\"upload\"}}"))
    if err != nil { panic(err) }
    request.Header.Set("Authorization", "Bearer " + os.Getenv("TODAYFILES_API_KEY"))
    request.Header.Set("Idempotency-Key", "replace-with-a-unique-request-key")
    request.Header.Set("Content-Type", "application/json")
    response, err := (&http.Client{Timeout: 30 * time.Second}).Do(request)
    if err != nil { panic(err) }
    defer response.Body.Close()
    body, err := io.ReadAll(io.LimitReader(response.Body, 1 << 20))
    if err != nil { panic(err) }
    if response.StatusCode >= 400 { panic(string(body)) }
    var result any
    if len(body) > 0 {
        if err := json.Unmarshal(body, &result); err != nil { panic(err) }
    }
    if err := json.NewEncoder(os.Stdout).Encode(result); err != nil { panic(err) }
}

Set Idempotency-Key to 1 to 255 characters. A random UUID is a good choice. Keep the key stable while retrying the same request. The key is optional, works on POST only, and is scoped to your account.

Understand a replay

The first response's status, body and Request-Id are retained for 24 hours. Repeating the same method, path and body returns that response with Idempotent-Replayed: true and the original Request-Id. Original-Request-Id also identifies the stored response. Use the original id when asking support about the operation.

A key reused with a different method, path or body returns 422 idempotency_key_mismatch. A second request arriving while the first runs returns 409 idempotency_key_in_use. Wait for the first request, then repeat it unchanged.

Responses larger than 256 KiB are not retained. After 24 hours a key can start a new operation. Do not use replay as a permanent record of your resources; save their returned ids in your application.

Retry deliberately

A retry still spends your request allowance. Honour Retry-After on a 429. Correct parameter errors before trying again with a new key. For uncertain outcomes, repeat the original request first so you can recover the original resource id.

What's next

Read the rate-limit headers or return to the quickstart.