Developer docs
Acoustic Index Read API
Search our library of acoustic materials, load the full product details with grouped acoustic measurements, and bring that data straight into your own planning tools, simulations, or apps.
Full acoustic product data
Pull descriptions, metadata, images, and grouped acoustic measurements for absorption, scatter, and diffusion into your own tools, simulations, or apps.
Two access modes
Authenticated `/v1/materials/*` endpoints for the full manufacturer dataset, plus public `/public/*` endpoints with no API key for AI agents, MCP servers, and Custom GPTs that need the lowest-friction entry point.
Predictable rate limits
Authenticated keys get 60 per minute and 1,000 per day (shared across your account). Public endpoints get 120 per minute per IP. Every response carries rate-limit headers.
Quickstart
Four steps to your first request.
Sign in, get approved once, and create your own keys. From there it's stable headers, predictable errors, and sensible rate limits.
1. Sign in
Use your normal Acoustic Index account. Both beta approval and your API keys are tied to it, so there is nothing extra to create.
2. Request beta access
Tell us what you are building, your app name, and a rough request volume. A human reviews each request, usually within a few days.
3. Create your API key
Once your account is approved, open the access page and generate as many keys as you need. You will see the full secret once, so copy it straight into your secret manager.
4. Call the endpoints
Add your API key to the `Authorization` header on every request, using `Bearer YOUR_API_KEY` as the value. That is the entire integration.
Authenticated base URL
https://acousticindex.com/api/v1
Versioned base for `/materials/*` endpoints. Needs a Bearer API key.
Public base URL
https://acousticindex.com/api/public
Unauthenticated base for `/search` and `/compare-products`. No API key, no approval flow.
Interactive reference
/api/reference
Full Scalar-rendered API reference with copy-paste request builders for every endpoint.
Authenticated rate limits
60/min and 1,000/day per account
Counted per user account, not per key. Creating more keys does not give you more capacity.
Public rate limits
120/min per IP
No daily cap. Suitable for agent runtimes that cannot carry an API key.
Beta access (authed only)
Sign in and request approval
Only authenticated endpoints require beta approval. Public endpoints are always open.
Copy and paste
One account step and two curl commands is all you need.
Create your key in the account UI once, then paste it into every request. No SDK, no client library, no boilerplate.
# Step by step 1. Sign in at https://acousticindex.com/api/access 2. Request beta access for your account 3. Wait for approval (usually a few days) 4. Create an API key from the access page Copy the full key the moment it appears. After that we only show the safe prefix.
# Search for materials matching "holz" curl "https://acousticindex.com/api/v1/materials/search?q=holz" \ -H "Authorization: Bearer YOUR_API_KEY" # Load the full detail for one product curl "https://acousticindex.com/api/v1/materials/PRODUCT_ID" \ -H "Authorization: Bearer YOUR_API_KEY"
Reference
Endpoint documentation.
Full field-by-field reference for every endpoint, with copy-paste request and response examples.
Authentication
The header you need to send, the rate-limit headers you get back, and how keys expire.
Search materials
Search acoustic materials and page through the results. Use this for pickers, browse views, and sync jobs.
Material detail
Load the full record for one product, including images, specs, and grouped acoustic measurements.
Client example
The typical flow: search, then load the detail.
Most integrations work the same way. Search for materials, pick a result, and only then fetch the full product detail when you actually need it.
const baseUrl = "https://acousticindex.com/api/v1";
const apiKey = process.env.ACOUSTIC_INDEX_API_KEY!;
async function apiFetch(path: string, init: RequestInit = {}) {
const response = await fetch(`${baseUrl}${path}`, {
...init,
headers: {
Authorization: `Bearer ${apiKey}`,
...(init.headers ?? {}),
},
});
if (!response.ok) {
const body = await response.json().catch(() => ({ error: "unknown" }));
throw new Error(`${response.status} ${body.error}: ${body.message}`);
}
return { data: await response.json(), headers: response.headers };
}
// Search with pagination
const { data: search } = await apiFetch("/materials/search?q=wood&limit=20");
console.log(`Found ${search.total_count} materials, has_more: ${search.has_more}`);
// Fetch detail with ETag caching
const id = search.items[0]?.id;
if (id) {
const { data, headers } = await apiFetch(`/materials/${id}`);
const etag = headers.get("ETag");
// Re-fetch with If-None-Match -- returns 304 if unchanged
const cached = await fetch(`${baseUrl}/materials/${id}`, {
headers: {
Authorization: `Bearer ${apiKey}`,
"If-None-Match": etag ?? "",
},
});
console.log(cached.status); // 304 if unchanged
}You only see published products
Search and detail only return products that are live on Acoustic Index. Anything unpublished or unknown comes back as `404 not_found`, so your client should treat that as a normal outcome.
Timestamps are UTC ISO 8601
Fields like `updated_at` and `expires_at` are always UTC ISO 8601 strings. Parse them as UTC and format them in the user's timezone yourself.
You see each key exactly once
When you create an API key, the full secret is shown on screen one time. After that only the safe prefix is visible, so copy the full key into your secret store immediately.
Pace your requests with the headers
Use `RateLimit-Remaining` and `RateLimit-Reset` from every response to decide when to slow down. That is much more reliable than hard-coded delays.
Errors always have the same shape
Every error comes back as `{ "error": "<code>", "message": "<explanation>" }`. Branch on `error` in your code and show `message` in logs so future-you can debug it.
Every response carries `X-Request-Id`
A unique UUID travels with every response. Drop it into your bug reports and we can find the exact request in our logs in seconds.