Skip to main content

Use the API from code

This guide is for developers who build on the API. It covers a small client, paging through a whole library, showing images in a web page, and keeping albums in step with your own data.

A small client​

Wrap the API in one function. It adds the key, turns errors into exceptions and keeps the base URL in one place.

auto.ts
const BASE = 'https://app.auto.inc/api';

export class AutoError extends Error {
constructor(public status: number, message: string) {
super(message);
}
}

export async function auto<T>(path: string, init: RequestInit = {}): Promise<T> {
const res = await fetch(BASE + path, {
...init,
headers: {
Authorization: `Bearer ${process.env.AUTO_API_KEY}`,
'Content-Type': 'application/json',
...init.headers,
},
});
const body = await res.json();
if (!res.ok) {
// 401 bodies use `message`. Every other error uses `error`.
throw new AutoError(res.status, body.error ?? body.message);
}
return body as T;
}

Walk the whole library​

Image lists have no cursor. Page backwards in time with endDate, and drop ids you have seen. The endDate filter includes its own time, so the last image of a page shows up again at the top of the next one.

type Image = { id: string; capturedAt: string | null; description: string | null };
type Page = { results: Image[] };

export async function* allImages(): AsyncGenerator<Image> {
const seen = new Set<string>();
let endDate: string | undefined;

while (true) {
const query = new URLSearchParams({ limit: '100' });
if (endDate) query.set('endDate', endDate);

const { results } = await auto<Page>(`/ext/v2/images?${query}`);
const fresh = results.filter((image) => !seen.has(image.id));
if (fresh.length === 0) return;

for (const image of fresh) {
seen.add(image.id);
yield image;
}
endDate = results[results.length - 1].capturedAt ?? undefined;
if (!endDate) return;
}
}

A library of 10,000 images takes about 100 requests. Run the walk once and store the ids. After that, ask only for images newer than the newest one you have, with startDate.

Show images in a web page​

Call the API from your server, never from the browser. The browser never sees the key. Auto also blocks cross-origin calls from sites it does not know.

The url on each image is signed and works for 15 minutes. Send it to the page as is:

server.ts
app.get('/gallery', async (req, res) => {
const { results } = await auto<Page>('/ext/v2/images?limit=24');
res.json(results.map((image) => ({ id: image.id, src: image.url, alt: image.description ?? '' })));
});
<img src="https://app.auto.inc/api/ext/v2/images/img_123/renditions/webp-medium?exp=...&sig=..." alt="..." />

Don't cache signed URLs for more than a few minutes. Cache the image id and ask again for a fresh URL. If you need a size other than the default, call Get an image and pick from renditions.

To keep the bytes, download a rendition with your key and store the file:

curl -o tram.webp \
-H "Authorization: Bearer $AUTO_API_KEY" \
https://app.auto.inc/api/ext/v2/images/img_123/renditions/webp-full

Keep an album in step​

Create an album reuses an album with the same title. That makes it safe to call again after a timeout. You can use the title as your key:

type AlbumResult = { result: { album: { id: string }; created: boolean; added: string[]; missing: string[] } };

const { result } = await auto<AlbumResult>('/ext/v2/albums', {
method: 'POST',
body: JSON.stringify({ title: 'Receipts 2026', imageIds: ids.slice(0, 100) }),
});

Each call takes at most 100 ids. For more, call Add images to an album in batches of 100. Check missing in each answer. It lists ids that Auto could not read, such as deleted images.

To take images out, use Remove images from an album. It is a POST to /images/removals, so the body survives clients that drop DELETE bodies.

Handle errors​

StatusRetry?Notes
400NoYour request is wrong. Log the message.
401NoStop. The key was revoked or is wrong.
404NoThe image may be deleted or outside the free plan window.
409NoShow the message to the user. It tells them what to change.
502 and 5xxYesBack off: wait 1 s, then 2 s, then 4 s.

Test without your own photos​

Make a second Auto account for tests and sync a few photos to it with Auto Photos. Keep its key apart from your real key. All accounts use the same production API.