Wiring an AI Image API Into an Agency Pipeline: Keys, Ledgers and Archives

By The Fellowi Team · · 8 min read

A creative agency desk at dusk with a wide monitor showing a grid of colourful image thumbnails beside a terminal window, external archive drives and a notebook with a hand-drawn flow diagram.

The API reference tells you how to make one picture. An agency has a different problem: thousands of pictures, a dozen clients, three people pressing buttons and one finance person asking at the end of the month who used what. None of that is hard, but every part of it is easy to get wrong in the first week. These are six rules, each one taken from how the API actually behaves rather than from how we wish it did. If you have not made a first request yet, start with the API intro.

Rule 1: one key per client, one wallet behind them

Keys are created in the API Console, each with a name, and the full key is shown exactly once. Name them after clients. A key that leaks, or a contract that ends, is revoked on its own and the others keep working. What keys do not do is split the money: every key on the account spends the same coin balance. If two clients must never share a balance, that is two accounts, and coins cannot be moved between accounts afterwards.

Rule 2: your ledger, keyed by your job id

The list endpoint returns the whole account, studio pictures included, not one key’s work. So keep your own ledger: client, job, generation id, coins charged. The cleanest way to tie them together is the Idempotency-Key header. Build it from your own job id, and a retried request after a dropped connection returns the generation that already exists instead of charging a second one. Give it a prefix unique to your agency, a random string is enough, because the key is checked across the whole service, not only your account.

POST /v1/api/images
Authorization: Bearer fk_live_key_for_client_a
Idempotency-Key: 7f1c2b90-client-a-deck-0042

{
  "prompt": "a linen shirt on a wooden hanger, soft window light",
  "quality": "standard",
  "aspectRatio": "4:5"
}

The answer is a 202 with the generation’s id and coinsCharged; write both into the ledger before doing anything else.

Rule 3: poll, do not wait

A generation is queued and runs in the background. Poll its status with a gentle interval (the response carries an estimate in etaMs while it is queued), and fire several jobs at once rather than one after another: the API allows more parallel jobs per account than the studio does, because that is its normal shape.

GET /v1/api/images/{id}          -> "queued", "generating", then "succeeded",
                                    or "failed" / "refunded" with refunded: true
GET /v1/api/images/{id}/content  -> the bytes, until the retention window ends
                                    (after that: 410 BYTES_EXPIRED)

Rule 4: treat failure as data

A failed generation refunds its coins automatically and says so in refunded. Its failureCode is one of a short fixed list: TIMEOUT and VENDOR_ERROR are worth one retry later, MODERATION_REJECTED means the prompt needs rewriting rather than repeating, and UNKNOWN covers the rest. Record the code in your ledger; a client whose brief keeps producing moderation failures is a conversation, not a retry loop. The economics of retries are in the pricing and failures post.

Rule 5: archive the moment it succeeds

The API is not an asset library. Finished files are deleted when the retention window on the product page ends, and after that the content request answers 410 BYTES_EXPIRED. Download every succeeded image into your own storage straight away, under the client and job from your ledger, and if a client must not have their pictures held by us at all, delete them through the API once archived.

Rule 6: check the limits from code, and put a human before delivery

Each key has a request rate, and the account has a daily image allowance. Both are reported by one call, so a batch job can check before it starts instead of failing half way:

GET /v1/api/me
-> { "keyName": "client-a", "coins": ..., "rateLimitPerMin": ..., "dailyImagesRemaining": ... }

The numbers themselves are on the product page. And before anything reaches a client, someone looks at it. A model can put six fingers on a hand or a wrong word on a sign, and an automated pipeline delivers that just as fast as it delivers a good picture.

What the API will not do for an agency

It has no sub-accounts, no per-client balances and no usage report per key: that bookkeeping is yours. There is no service level agreement and no guaranteed delivery time, so do not promise a client minutes you have not measured. It does not make a generated picture yours in the copyright sense, as who owns AI imagesexplains, even though commercial use is allowed and we take no share. And a real person’s face still needs that person’s permission, however the request arrives.

Budgeting the coins behind all of this is covered in what a team actually spends, and the studio for the hand-made pictures is Fellowi Images.

Questions this post answers

Can each client have its own balance?

No. Every key on an account spends the same coin balance, so separate balances would mean separate accounts. Most agencies keep one account, give each client its own key, and do the per-client accounting in their own ledger.

How do I stop a retried request from being charged twice?

Send an Idempotency-Key header built from your own job id. A request that repeats the same key returns the generation that already exists instead of starting and charging a new one.

How long can I download a finished image?

Until the retention window shown on the product page ends; after that the content request answers 410 BYTES_EXPIRED. Download every finished image into your own storage as soon as it succeeds.

Try it for yourself

A warm, private AI companion - 7 days free with 30 messages, no card needed.

Pricing and limits

Keep reading