Start

Limits and errors

Budgets, warning headers, and how to read a 400 or 403.

Every keyed call spends one automation call when the key is accepted. A failed solve refunds the feature meter it spent, such as a polar or compute credits. It does not refund the automation call. The counter resets with the calendar month in UTC.

Work this page from top to bottom. Read Before you call this API, then Request syntax, then the full Step by step walkthrough and the Quick checklist. Fill each payload field from the parameters table, send one of the language samples, and match the HTTP status to the accepted body or to a rejected body. Sample numbers show field names only — they are not measured aerodynamic results. If a field or status is unclear, use the contact links at the end and include the status and the error text.

How to use this documentation page

  1. Skim the intro so you know what meter this analysis spends and what geometry it needs.
  2. Complete the step-by-step walkthrough once with the dummy shapes, then again with your live key and real inputs.
  3. Copy a language sample, change only the values you must change, and keep JSON key names identical.
  4. On every response, read status first. Only then parse coefficients, gates, or file content.
  5. When automation returns 202, open Jobs and usage and poll until the job finishes.

Read the meters

GET https://henfoil.hendoi.com/api/v1/usage

Before you call this API

  • You have an active HENDOI account and a live HENFOIL API key (hfk_…).
  • You know which plan meters this call spends (automation apiRequests, and often polars, optimize, or compute credits).
  • You have either a stored airfoilId, a NACA code, or coordinate / .dat text ready when the endpoint needs geometry.
  • You will treat every numeric sample on this page as a shape guide, not as measured flight data.

Request syntax

Every call has the same four parts. Fill them in this order.

  1. Method. GET.
  2. URL. https://henfoil.hendoi.com/api/v1/usage. The host is the production API. Do not change it.
  3. Header. Authorization: Bearer hfk_demo_4c91e2ab8d07. Replace the dummy key with the key from Settings, then API, then Generate now. You can send the raw key in X-Henfoil-Key instead, with no Bearer prefix.
  4. Body. None. Do not attach JSON.

Step by step

Follow this guide in order. Each step says what to type, where it goes, and what to check next. After the last step, compare your HTTP status with the accepted body and the rejected bodies further down.

  1. Before you start. Sign in at https://hendoi.com/login, open HENFOIL, then Settings → API → Generate now. Copy the full hfk_… key once. Confirm your plan still has usage remaining for automation calls.
  2. Confirm the endpoint. You will send GET to https://henfoil.hendoi.com/api/v1/usage. Keep the production host. Do not point samples at localhost in a shipped integration.
  3. Attach the key. Prefer Authorization: Bearer hfk_…. Or send the raw key in X-Henfoil-Key with no Bearer prefix. Never put the key in the JSON body or in a query string.
  4. Leave the body empty. Do not send Content-Type: application/json with an empty object unless a sample on this page says otherwise. A stray body can confuse proxies and clients.
  5. Send the key. This call has no body and no query parameters.
  6. Read usage.apiRequests, usage.polars, and usage.computeCredits.
  7. If a later call returns 403, open meter in that body and compare it with this payload.
  8. Send the request. Use any of the six language samples below. Expect HTTP 403 when the call matches this page's accepted example (or HTTP 202 with jobId when a long solve is queued).
  9. Read the JSON by name. On success, start with error, code, meter, used, limit, remaining, plan. Ignore sample coefficient magnitudes — they are placeholders for field names only.
  10. Handle failure before success fields. If status is 400, 401, or 403, read error (and meter on 403). Do not parse lift or drag from an error body.
  11. Verify before the next call. Confirm status, remaining automation budget (X-Henfoil-Api-Remaining or GET /api/v1/usage), and that honesty / gate fields (when present) match what you expect for a screening result — not a certification claim.
  12. If you are stuck. Copy the HTTP status and the full error string, then use the contact block at the bottom of this page (WhatsApp or support@hendoi.com).

Quick checklist

  • □ Method is GET and URL path is exact.
  • □ Live API key is in the Authorization (or X-Henfoil-Key) header.
  • □ No JSON body is attached.
  • □ Client branches on HTTP status before reading aerodynamic fields.
  • □ Error path logs error / meter for support.

How to fill the payload

Treat the payload as a form. Each name is a JSON key. Send numbers as numbers, without quotes. Send text in quotes. Omit an optional key when you want the server default. Send exactly one geometry source when the table says the field is one of a set.

This call has no JSON body and no query fields. The only value you replace is the API key in the header.

Example request

The key hfk_demo_4c91e2ab8d07 is a dummy. It is not a live key, and the server rejects it. Replace it before you send the call. The other values are dummy parameters in the same shape the server reads, so you can see where each number goes.

GET https://henfoil.hendoi.com/api/v1/usage
Authorization: Bearer hfk_demo_4c91e2ab8d07

Example response body

This sample is the JSON for HTTP 403. Read the status before the fields. The numbers are placeholders for the field names.

{
  "error": "API usage limit reached.",
  "code": "QUOTA_EXCEEDED",
  "meter": "apiRequests",
  "used": 500,
  "limit": 500,
  "remaining": 0,
  "plan": "student"
}

Read the body by name:

  • error — text, such as an id, a name, or a message.
  • code — text, such as an id, a name, or a message.
  • meter — text, such as an id, a name, or a message.
  • used — a number. Read the live value from your own response. The sample only shows the type.
  • limit — a number. Read the live value from your own response. The sample only shows the type.
  • remaining — a number. Read the live value from your own response. The sample only shows the type.
  • plan — text, such as an id, a name, or a message.

Other responses you can see

  • That JSON is the 403 body, not the 200 usage body. The 200 body is under usage.
  • meter apiKeyAllocation means this key used the calls the team admin assigned. Other keys still work.
  • meter polars, computeCredits, optimizeJobs, or robustnessRuns is the platform meter for that analysis.

If the request is not accepted

A rejected call is still JSON. Read the HTTP status, then the error string. Do not look for lift or drag fields in these bodies. Fix the named problem and send the same call again.

HTTP 400, missing or unusable input. The message changes with the field. The shape does not:

{
  "error": "Provide coordinates, text, or airfoilId."
}

HTTP 401, missing, unknown, or deactivated key. No automation call is spent:

{
  "error": "This API key is deactivated or was not recognized. Only an active key can call the API."
}

HTTP 403, a meter is used up. meter tells you which one. apiRequests is the automation budget. apiKeyAllocation is the calls assigned to this key:

{
  "error": "API usage limit reached.",
  "code": "QUOTA_EXCEEDED",
  "plan": "student",
  "upgradeTo": "professional",
  "pricingPath": "/pricing",
  "meter": "apiRequests",
  "used": 500,
  "limit": 500,
  "remaining": 0
}

When something goes wrong

  • HTTP 503: metering or the solver is briefly unavailable. Wait and send the same body again.
  • HTTP 404: the airfoil id or job id was not found. Check the id from the earlier response.
  • HTTP 401: the key is missing, unknown, or deactivated. No call is spent. Generate a new key and send that value.
  • HTTP 403 with code QUOTA_EXCEEDED: read meter. apiRequests is the automation budget. apiKeyAllocation is this key's assigned calls. The other meter names are the platform limit named in the message.
  • HTTP 400: read error. It names the missing field or the geometry problem. Fix that field and send the call again.
  • HTTP 202 with jobId: the solve is queued. Poll Jobs and usage until status is COMPLETED, COMPLETED_WITH_WARNINGS, FAILED, or CANCELLED. Then GET the job without partial=1.

How each language returns a bad response

  • cURL. The body prints first. The last line from -w is the HTTP status. 400 still prints a JSON body.
  • Node.js. fetch does not throw on 400, 401, or 403. Branch on res.status, then read data.error.
  • C#. GetAsync and PostAsync do not throw on those statuses. Read StatusCode, then the body string.
  • Python. urlopen raises urllib.error.HTTPError. The status is e.code. The JSON is e.read().decode().
  • PHP. curl_exec returns the body for a 400. The status is CURLINFO_HTTP_CODE. A 400 means the server answered.
  • Java. send returns the status and the body together. A 400 does not throw.
import json
from urllib.error import HTTPError
from urllib.request import urlopen
# req is the Request built in the Python sample below.
try:
    with urlopen(req) as res:
        print(res.status)
        print(json.load(res))
except HTTPError as e:
    print(e.code)
    print(json.loads(e.read().decode()))

Useful tips

  • Replace the dummy key before the first real call. A 401 on the sample key is expected.
  • Check the HTTP status before you read any coefficient. An error body has error, not a polar.
  • Read X-Henfoil-Api-Remaining before a loop. X-Henfoil-Api-Warning appears when fewer than one fifth of the calls remain.
  • Copy a sample with the Copy button, then change only the values you intend to change. Leave the key names as written.
  • If the error text does not match the body you sent, contact us with the status code and that text. The link is at the bottom of this page.

Samples

The six programs below send the same method, URL, header, and payload. The paragraph above each program says which line is the payload and which line is the response.

Send it in cURL

There is no JSON body. The URL is the first quoted argument. Replace the dummy key in the Authorization header. -w prints the HTTP status on the line after the body.

curl -s \
  "https://henfoil.hendoi.com/api/v1/usage" \
  -H "Authorization: Bearer hfk_demo_4c91e2ab8d07" \
  -w "\n%{http_code}\n"

Send it in Node.js

There is no body. fetch returns the response even when the status is 400 or 403. res.status is the HTTP code. data is the parsed JSON.

const res = await fetch("https://henfoil.hendoi.com/api/v1/usage", {
  headers: { Authorization: "Bearer hfk_demo_4c91e2ab8d07" }
});
const data = await res.json();
console.log(res.status, data);

Send it in C#

There is no request content. StatusCode is the HTTP code. The string on the next line is the response body, including an error field when the call was rejected.

using System.Net.Http.Headers;
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", "hfk_demo_4c91e2ab8d07");
var response = await client.GetAsync("https://henfoil.hendoi.com/api/v1/usage");
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine((int)response.StatusCode);
Console.WriteLine(json);

Send it in Python

urlopen returns only a successful response. On 400, 401, or 403 it raises HTTPError. Read e.code and e.read() in that handler. The pattern is in the section above.

import json
from urllib.request import Request, urlopen
req = Request("https://henfoil.hendoi.com/api/v1/usage", headers={"Authorization": "Bearer hfk_demo_4c91e2ab8d07"})
with urlopen(req) as res:
    print(res.status)
    print(json.load(res))

Send it in PHP

There is no CURLOPT_POSTFIELDS. CURLINFO_HTTP_CODE is the status. $body is the response text for both a 200 and a 400.

$ch = curl_init("https://henfoil.hendoi.com/api/v1/usage");
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ["Authorization: Bearer hfk_demo_4c91e2ab8d07"],
]);
$body = curl_exec($ch);
echo curl_getinfo($ch, CURLINFO_HTTP_CODE), "\n", $body;
curl_close($ch);

Send it in Java

There is no request body publisher. statusCode() is the HTTP code. body() is the response text. A 400 does not throw.

var client = java.net.http.HttpClient.newHttpClient();
var request = java.net.http.HttpRequest.newBuilder()
    .uri(java.net.URI.create("https://henfoil.hendoi.com/api/v1/usage"))
    .header("Authorization", "Bearer hfk_demo_4c91e2ab8d07")
    .GET()
    .build();
var response = client.send(request, java.net.http.HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body());

Related pages

If you are unsure, contact us

You do not have to guess the payload. Call or WhatsApp +91-9677261485. The message already names this page. Or email support@hendoi.com. Paste the HTTP status and the error text from the response so we can answer from the same request you sent.

Contact us if you are stuck

Call or WhatsApp +91-9677261485. The message already names this page. Or email support@hendoi.com. Paste the HTTP status and the error text from the response.

Call usChat with us