REST API reference
The upload.ad REST API (v1) lets you upload creatives to your Meta and TikTok ad accounts, track upload jobs, and manage ad copy variants from any language that can make HTTPS requests.
Base URL: https://upload.ad
The reference is organized by resource:
- Uploads: send files and track the jobs that push them to your ad platforms
- Creatives: the files in your library
- Copy variants: ad texts attached to each creative
- Webhooks: signed events when an upload completes or fails
The API is also described by an OpenAPI specification.
Conventions
Authentication. Create an API key at upload.ad/dashboard/settings/api-keys and send it on every request. API access requires an active subscription: keys can only be created on a paid plan, and requests return 402 if the plan lapses.
A key is bound to the workspace that was active when it was created and acts with its creator's permissions in that workspace. Requests return 403 when the key's creator lacks the permission for an action. Workspace owners and admins can see and revoke every key bound to their workspace.
Authorization: Bearer ua_live_...Format. Requests and responses are JSON, except POST /api/v1/uploads, which takes multipart/form-data. Timestamps are ISO 8601 strings in UTC.
Errors. Errors return a 4xx or 5xx status with a JSON body:
{ "message": "Description of the problem" }| Status | Meaning |
|---|---|
400 | Malformed request body or parameters |
401 | Missing or invalid API key |
402 | An active subscription is required |
404 | Resource not found, or not visible to your account |
409 | The resource is not in a state that allows the operation |
Account
GET/api/v1/me
Returns the authenticated account. Useful as a connectivity and key check.
curl https://upload.ad/api/v1/me \
-H "Authorization: Bearer $UPLOADAD_API_KEY"const res = await fetch('https://upload.ad/api/v1/me', {
headers: { Authorization: `Bearer ${process.env.UPLOADAD_API_KEY}` }
});
const { account } = await res.json();import os, requests
res = requests.get(
"https://upload.ad/api/v1/me",
headers={"Authorization": f"Bearer {os.environ['UPLOADAD_API_KEY']}"},
)
account = res.json()["account"]<?php
$ch = curl_init('https://upload.ad/api/v1/me');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer ' . getenv('UPLOADAD_API_KEY')]);
$account = json_decode(curl_exec($ch), true)['account'];
curl_close($ch);package main
import (
"fmt"
"io"
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("GET", "https://upload.ad/api/v1/me", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("UPLOADAD_API_KEY"))
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}require "net/http"
require "json"
uri = URI("https://upload.ad/api/v1/me")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{ENV['UPLOADAD_API_KEY']}"
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
account = JSON.parse(res.body)["account"]import java.net.URI;
import java.net.http.*;
public class Me {
public static void main(String[] args) throws Exception {
HttpRequest req = HttpRequest.newBuilder(URI.create("https://upload.ad/api/v1/me"))
.header("Authorization", "Bearer " + System.getenv("UPLOADAD_API_KEY"))
.build();
HttpResponse<String> res = HttpClient.newHttpClient().send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(res.body());
}
}using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization",
$"Bearer {Environment.GetEnvironmentVariable("UPLOADAD_API_KEY")}");
var body = await client.GetStringAsync("https://upload.ad/api/v1/me");
Console.WriteLine(body);{
"account": {
"id": "acc_123",
"name": "Acme Inc",
"email": "ads@acme.com",
"plan": "growth",
"credits": 240,
"trialEndsAt": null
}
}| Field | Type | Description |
|---|---|---|
id | string | Account id |
name | string | Account name |
email | string | Account email |
plan | string or null | Current plan, null if not on a plan |
credits | integer | Remaining credits |
trialEndsAt | string or null | Trial end date, null when on a plan |