Skip to main content

Higgsfield API: What It Exposes, What It Costs, and the 7-Day Output Window

One base URL, a key pair in the Authorization header, and an asynchronous queue you poll or webhook. Here is the whole Higgsfield API surface, the concurrency ceiling that stops you first, and the billing and retention rules worth reading before you write any code.

Mauricio Valdivia

Mauricio Valdivia

·12 min

Higgsfield API: What It Exposes, What It Costs, and the 7-Day Output Window

The API hands you a queue ticket, not a video

The first call surprises people. You POST a prompt to a model endpoint, you brace for a long wait, and the response comes back in well under a second. There is no video in it. There is a request id, two URLs and the word queued.

That is the whole shape of the Higgsfield API, and everything else follows from it. Generation is asynchronous, so the submission is a ticket and the media arrives later, through a status endpoint you poll or a webhook you registered at submission time. The docs put it plainly: a successful submission creates a request and returns immediately while the work continues in the background.

This is a working reference for that surface. Base URL and auth shape, the request lifecycle and its six states, the ceiling you will hit first and the odd HTTP code it uses, how billing and refunds behave, and the retention window that quietly makes storage your problem. It is not a launch write-up. The submit-then-retrieve shape is the API's settled contract, old enough that Higgsfield's own Python and TypeScript clients wrap the polling for you, which is exactly why it is worth documenting properly rather than treating as news.

One thing this post will not do is quote you a plan price. Higgsfield sells paid subscription plans, and the place to read the current numbers is its own pricing page. What the docs publish, and what you can act on today, is the credit machinery underneath: an endpoint that prices a call before you make it.

What the API actually exposes

The surface is small, which is good news. Most of the integration work is in lifecycle handling, not in learning endpoints.

One base URL, one generated reference

Everything lives under https://api.higgsfield.ai, and the reference is not hand-written: Higgsfield states that the API reference is generated from the public OpenAPI specification and includes model-specific generation schemas plus the shared status and cancellation operations. That matters more than it sounds. A generated reference means the parameter list for a given model is the parameter list the server validates against, so the schema in the sidebar is the contract, not a description of it.

Generation endpoints are model-paths. The quickstart submits to a path of the form /higgsfield-ai/soul/v2/standard, and the docs tell you to use the generation endpoint available to your account, because model availability is account-scoped rather than universal.

Two shared operations on top of the model endpoints

Beyond the per-model generation paths, there are exactly two operations every integration uses:

  • Get request status, GET /requests/{request_id}/status, which returns state and output together.
  • Cancel a queued request, which stops work that has not started processing.

Those two are the whole cross-model surface the reference enumerates. If you want a job table, you build it yourself, keyed on the request ids you stored.

Input media: a public URL, or a presigned upload

Models that take an image, a video or an audio file want a URL. If your media is already on a public https URL you pass it directly. If it is not, there is a short upload dance:

  1. POST /files/generate-upload-url with the content type you intend to send.
  2. PUT the bytes to the presigned upload_url it returns, sending every header that came back in upload_headers.
  3. Pass the returned public_url into the model parameter that takes an input URL.

Two details worth pinning to the wall: that upload URL expires after one hour, and you must not send Higgsfield API credentials to the presigned storage URL. The supported content types are a short list: image/jpeg and image/jpg, image/png, image/webp, image/gif, audio/wav and audio/x-wav, and video/mp4. The content type you upload with has to match the one you created the presigned URL with.

Real UGC creators talking to camera in a row of video cards
Novoads · UGC video ads with AI, ready in minutes.
Try now

Authentication is a key pair, not a bearer token

This trips up anyone who integrates a dozen AI APIs a year and reaches for the muscle memory of Authorization: Bearer sk-....

Two values, one header

A Higgsfield credential is a pair. The docs say each credential consists of a key ID and a secret, both created and managed in Higgsfield Cloud, and both go into a single header:

Authorization: Key YOUR_KEY_ID:YOUR_KEY_SECRET

The FAQ is blunt about the alternative, telling you not to use a bearer token and not to expose the secret in browser or mobile code. The rest of the credential guidance reads like a security review that has already happened:

  • Store credentials in a secrets manager or encrypted environment variables.
  • Use separate credentials for development and production.
  • Never put them in URLs, logs, screenshots or support messages.
  • Rotate immediately if a credential may have been exposed.

The legacy headers still work, and should not be your default

The API also accepts legacy hf-api-key and hf-secret headers, and Higgsfield says new integrations should use the Authorization header. If you are reading someone's older sample code and wondering why it has two headers where the docs show one, that is why. Both paths authenticate; only one is the documented direction of travel.

What a 401 proves, and what it does not

Missing, malformed or invalid credentials return a 401 with a detail body. Useful, and narrower than it looks. Higgsfield notes that authentication identifies the account, but individual models may have separate access restrictions, and an unavailable model answers with a different code depending on why:

  • 404 when the request or model is not found for this account.
  • 423 when the model is temporarily blocked.
  • 503 when the model is disabled or not ready.

So a working key is not proof of a working endpoint. Probe the specific model path you intend to ship against, with the account that will ship it, before you write the integration around it.

The request lifecycle: six states, four of them final

The lifecycle page is the one to read twice. Everything that makes an integration robust or fragile lives here.

Three URLs come back with the request id

The accept response is small and complete:

{
  "status": "queued",
  "request_id": "d7e6c0f3-6699-4f6c-bb45-2ad7fd9158ff",
  "status_url": "https://api.higgsfield.ai/requests/d7e6c0f3-6699-4f6c-bb45-2ad7fd9158ff/status",
  "cancel_url": "https://api.higgsfield.ai/requests/d7e6c0f3-6699-4f6c-bb45-2ad7fd9158ff/cancel"
}

Higgsfield's instruction is to use the URLs from the response instead of constructing them manually, and to store the request_id as soon as a request is accepted, because it is the stable identifier used by polling, cancellation, webhook deduplication and support. Treat that id as the primary key of your own job row, written before you do anything else with the response. A minimum useful row is five columns:

  • The request_id, written first, before any other handling.
  • The status_url and cancel_url exactly as returned.
  • The current status, updated only from a response you actually read.
  • The x-correlation-id from the submit response, for support tickets.
  • The output URLs once terminal, plus where you copied them.

The six statuses

StatusTerminalWhat it means for your code
queuedNoWaiting to start. Still cancelable.
in_progressNoRunning. Cancellation is closed.
completedYesOutput URLs available. Copy them.
failedYesGeneration failed. Not charged.
nsfwYesModeration rejected it. Not charged.
canceledYesStopped before processing. Refunded.

Two of those six deserve attention when you write the handler. nsfw is a terminal state, not an error envelope, so a client that only branches on completed and failed will hang on it. And cancellation is narrower than the name suggests: it is available only while every job in the request remains queued, a successful cancel returns 202 with an empty body, and a cancel after processing has started returns a 400.

Poll, or take the webhook, or both

Polling is documented with a concrete strategy rather than left to taste:

  • Start at a two-second interval and increase gradually to ten seconds.
  • Add random jitter when many workers poll at once.
  • Stop on completed, failed, nsfw or canceled.
  • Treat 401 and 404 as stop-and-fix conditions, not retry conditions.
  • Retry only 5xx and network failures, with exponential backoff.

The alternative is a webhook, configured by passing an https endpoint in the hf_webhook query parameter at submission. The contract it puts on your side is specific:

  • The endpoint must be publicly reachable over HTTPS, accept a JSON body, and respond within ten seconds.
  • Network failures and 5xx are retried for up to two hours.
  • 4xx is permanent. A bad deploy that returns 400 for an hour loses those results to the webhook path entirely.
  • Duplicate deliveries are possible, so deduplicate on request_id plus terminal status.

Higgsfield's own recommendation for long-running production workloads is to use webhooks and keep polling as a recovery path, which is the right answer: a webhook you cannot replay is a single point of failure, and the status endpoint is the replay.

Concurrency is the ceiling that will actually stop you

If you have integrated video APIs before, you are braced for a requests-per-minute budget. That is not the shape here, and the mismatch is where first integrations quietly lose work.

The published limit is in-flight requests

Higgsfield states that the primary generation limit is concurrency: the number of requests that may be queued or processing at the same time. Some models can also carry model-specific limits on top. The actual numbers depend on the account, the subscription and the selected model, and the docs point you at Higgsfield Cloud for the authoritative values.

Note what this does to your mental model of throughput. A per-minute budget rewards spreading submissions out. A concurrency budget rewards keeping exactly N jobs in flight and refilling a slot the moment one goes terminal. Those are different programs.

A 400 that behaves like a 429

When you hit the ceiling, the API returns a 400 Bad Request with a detail message about the maximum number of concurrent requests having been reached. The example in the docs shows a limit of 4, which illustrates the message rather than fixing a universal number.

This is worth a defensive note in your error handler. A 400 normally means "your request was wrong, do not retry it", and a generic HTTP client will happily treat it that way and drop the job. Here the same code can mean "your request was fine, there was no room", which is retryable after a wait. Higgsfield's own errors page lists the 400 row with three meanings at once:

  • Invalid parameters. Fix the request, then retry.
  • Rejected input. Fix the input, then retry.
  • Concurrency reached. Change nothing, wait, retry.

The same page warns against parsing human-readable messages to make permanent business decisions, which leaves you in an honest bind: branch on the message to tell the third case from the first two, and keep that branch narrow and observable, because it is exactly the kind of string that changes without warning.

No Retry-After, so the backoff is yours

The docs say the API does not currently publish standard rate-limit response headers or Retry-After, and tell you to treat the limits shown in your dashboard as authoritative. There is a second absence in the same family, stated on the errors page: submissions do not currently accept an idempotency key, which is why the guidance is not to automatically repeat a generation POST after an ambiguous timeout. A retried submission is a second billable job, not a deduplicated one.

Put together, the client design writes itself:

  • Cap submissions with a worker pool or semaphore sized to your account limit.
  • Keep polling traffic separate from generation submission concurrency.
  • Back off with exponential delay plus jitter, never a tight loop.
  • On an ambiguous submit timeout, reconcile before resubmitting, not after.
  • Record the x-correlation-id header, present on every response, next to the request_id.
A UGC creator filming a skincare product review on a phone
Novoads · UGC video ads with AI, ready in minutes.
Try now

Billing: estimate first, and read the refund rules

Higgsfield charges successful generation requests using account credits, and the exact cost depends on the selected model and parameters. That sentence is doing a lot of work, because it means cost is a function of the call, not of the endpoint, and you can find it out before you spend anything.

The estimate endpoint prices the exact call

There is a pre-flight price oracle, which is more than some vendors give you: fal publishes a static per-image table for GPT Image 2.5 and leaves the arithmetic to you. You POST the same model parameters to an estimate path, and it answers with both a credit figure and a USD figure:

{
  "credits": "1.500",
  "usd": "0.094"
}

Read that block carefully, because it is not a price list. Higgsfield labels those numbers itself: the values illustrate the response format, and the estimate returned for your authenticated account is the authoritative amount. So the shape is the useful part. The docs tell you to treat the estimate returned for your authenticated account as the authoritative amount, which is a strong hint that the number is account-specific rather than a public rate card, and it is the reason a hardcoded cost table in your code will drift.

Wire it in early. An estimate call in front of a batch is the difference between a run that fails fast on an insufficient-credit check and one that discovers the problem as a wall of 403 responses halfway through. The pattern is the same one that makes any credit-metered stack predictable, and if you want the conceptual version of it, our explainer on how AI video credits work covers the accounting side.

What is not charged

The refund rules are unusually clear, and they are the part most integrations get to lean on:

  • Failed and nsfw requests are not charged, and credits reserved at acceptance are refunded automatically.
  • A request cancelled while still queued is refunded.
  • A generation that exceeds its model-specific timeout is marked failed, and the FAQ states you are not charged for it.

The practical consequence: moderation rejections cost nothing to retry, so a prompt that trips content policy is a schedule problem rather than a budget problem. The one that does cost you is the ambiguous submit, because of the missing idempotency key above.

Credits expire in a year. Output expires in a week.

Two clocks, and the short one is the dangerous one.

Credits expire one year after they are added to your account balance, which is a purchasing consideration rather than an engineering one. Output retention is an engineering one. Generated output is accessible for at least seven days after creation and may be removed after that period, and both the billing page and the FAQ tell you to download completed files to your own storage for long-term retention.

Treat that as a required step in the pipeline, not a nice-to-have. The same reasoning applies one layer up, to the model itself: Suno retiring its whole pre-v6 line is the version of this problem where the file survives and the thing that made it does not. A completed request whose URLs you never copied is a charged generation with no artifact, and there is no endpoint that brings it back. Anyone who has watched a creative library quietly hollow out because the CDN links aged out knows this failure looks like nothing at all until someone opens an old campaign folder.

A worked run: 20 ad variants against a 4-slot ceiling

Abstractions get tested by a batch. Here is one that puts every rule above under load at once, using the docs' own example concurrency of 4 as the account limit.

The shape of the job

A skincare brand wants 20 variants of one product clip for a Meta test: same product, five hooks, four visual treatments. Every variant is an independent generation request. If you are sizing a test like this, how many ad creatives you actually need is the prior question, and keeping one actor consistent across variations is the one that decides whether the set reads as a campaign or a pile.

Where the naive version breaks

Two failures, and only one of them is loud:

  • The concurrency drop. The naive script fires all 20 submissions in a loop. Four are accepted. Sixteen come back 400, the generic client files 400 under permanent client error, and sixteen variants vanish. The run reports success. You find out when someone counts the files.
  • The double submit. A submit times out at the proxy, the script retries, and both land. One prompt, two billable generations, and no idempotency key to collapse them. At one variant nobody notices. At a nightly batch it is a line item.

What the fixed version looks like

  • A semaphore of 4 around submissions, refilled when a request goes terminal, so the ceiling is never tested.
  • A separate poller on its own schedule reading status_url from the stored rows, never sharing the submission budget.
  • An estimate call before the batch, multiplied by 20, checked against the balance.
  • A reconcile step on ambiguous timeouts: look for an in-flight request that matches before resubmitting.
  • A copy step on every completed, moving the media into your own bucket the same hour.

That is maybe eighty lines of glue, and it is the difference between an API that works in a notebook and one that runs a campaign. Render latency varies widely by model, which is worth knowing before you set your polling timeout: we measured render times across models rather than guessing.

Novoads UGC ad templates gallery
Novoads · UGC video ads with AI, ready in minutes.
Try now

How Novoads solves the assembly, not the generation

Everything above is a generation API. You submit parameters, you get a clip. That is the right tool if you are building a product where video is a feature, and Higgsfield's version of it is clean: a generated reference, refund rules stated plainly, a documented polling strategy, and an estimate endpoint that prices the exact call before you make it.

It is the wrong unit of work if what you need is an ad. An ad is a script that says a specific claim, a person who says it convincingly, lip-sync that holds, captions, an aspect ratio per placement, and twenty variants that differ where you want them to differ. Stitching those from raw clips is the actual job, and it is the part a generation endpoint hands back to you.

Novoads is built at that unit. You upload a product photo and write or auto-generate a script, pick an AI actor, and get a finished ad with voice and lip-sync rather than a clip to assemble. Underneath it runs the same class of frontier engines the rest of the category rents, including Seedance 2.0 and the half-price Seedance 2.0 Mini, Kling v3 Pro and Google Veo 3.1, so the realism question is a tie and the argument moves to what a usable ad costs. It starts at $49/month on the Inicial plan with 50 credits per month, cancel anytime, and product-to-ad image generation is a published 0.3 credits per image rather than a number you discover on the invoice.

The two tools also meet in a different place worth knowing about, because Higgsfield's agent surface is a separate door with separate billing from the API described here. We took that apart in Higgsfield MCP explained, and if you are weighing the whole platform rather than its API, the alternatives comparison and the head-to-head are the two to read.

A generation API gives you clips. Someone still has to make the ad.

The Higgsfield API is a well-shaped piece of infrastructure, and the parts that look like rough edges on a first read are mostly honest disclosure: the 400 that means "no room", the missing Retry-After, the missing idempotency key, the seven-day window on your own output. Vendors who hide those let you find them in production instead.

Integrate against the shape rather than against the happy path. Cap concurrency, poll with jitter, take the webhook and keep the poll as recovery, estimate before you spend, and copy every finished file into storage you control within the week. Do that and the API is boring in the best sense.

Then ask what you are actually building. If the answer is a product feature that needs pixels, this is your endpoint. If the answer is next quarter's ad creative, the endpoint was never the hard part. The assembly was.

Frequently Asked Questions

What is the Higgsfield API base URL?

https://api.higgsfield.ai. Higgsfield's API reference states it directly and adds that all endpoints require the Authorization header. The reference itself is generated from the public OpenAPI specification and covers model-specific generation schemas plus two shared operations: get request status and cancel a queued request. The FAQ repeats the same instruction, telling you to send requests to https://api.higgsfield.ai and authenticate server-side, and not to use a bearer token.

How do you authenticate with the Higgsfield API?

With a key ID and a secret, created and managed in Higgsfield Cloud. Both values go into a single header in the form Authorization: Key YOUR_KEY_ID:YOUR_KEY_SECRET. Legacy hf-api-key and hf-secret headers still work, but the docs say new integrations should use the Authorization header. Credentials are server-side only: the documentation tells you not to call the API from browser or mobile application code, because anyone who can inspect the application can extract its secret.

Does the Higgsfield API return the video right away?

No. Generation is asynchronous. A successful submission creates a request and returns immediately while the work continues in the background, handing back a request_id, a status_url and a cancel_url with the status queued. You then either poll the status URL until the request reaches a terminal state, or pass an https endpoint in the hf_webhook query parameter and receive the result when it finishes. Higgsfield's recommended pattern for production is a webhook with polling kept as a recovery path.

What are the Higgsfield API rate limits?

They depend on the account, the subscription and the selected model, and the authoritative figures are the ones shown in your Higgsfield Cloud dashboard. The shape is what matters when you design the client: the primary generation limit is concurrency, the number of requests that may be queued or processing at the same time, and some models can carry their own limits on top. Reaching the ceiling returns a 400 with a detail message about the maximum number of concurrent requests, and the API does not currently publish standard rate-limit response headers or Retry-After.

Are failed Higgsfield API requests charged?

No. Higgsfield charges successful generation requests using account credits, and its billing page states that requests ending as failed or nsfw are not charged, with any credits reserved at acceptance refunded automatically. A request cancelled before processing starts is also refunded. The FAQ adds that a generation exceeding its model-specific timeout is marked failed and is not charged either.

How long does Higgsfield keep generated files?

At least seven days. The billing and retention page states that generated output is accessible for at least seven days after creation and may be removed after that period, and the FAQ puts the same rule as a minimum of 7 days from creation with files removable at any time afterwards. Both pages tell you to download completed files into your own storage for long-term retention, which makes the copy step part of the integration rather than an afterthought.

Key Takeaways

  • The whole surface is one base URL, https://api.higgsfield.ai, with model-specific generation endpoints plus two shared operations: get request status and cancel a queued request. The reference is generated from the public OpenAPI specification.
  • Authentication is a key pair, not a bearer token. You send Authorization: Key YOUR_KEY_ID:YOUR_KEY_SECRET, server-side only, and the docs say plainly not to call the API from browser or mobile code.
  • Generation is asynchronous. A submission returns a request_id, a status_url and a cancel_url at status queued, and you either poll that URL or pass an https endpoint in the hf_webhook query parameter.
  • The published limit is concurrency, not requests per second, and hitting it returns a 400 rather than a 429. There are no standard rate-limit headers, no Retry-After, and submissions do not currently accept an idempotency key.
  • Estimate before you submit: the estimate endpoint returns a credit figure and a USD figure for the exact parameters. Failed, moderated and cancelled-while-queued requests are refunded, credits expire after a year, and output is only guaranteed for seven days.
Mauricio Valdivia

Mauricio Valdivia

Founder of Novoads

Mauricio is the founder of Novoads, where he works to democratize video advertising with AI for brands in Latin America.