When to use it

Use it when someone is looking for a creative director for a product or brand launch, a brand identity system, a museum or interactive experience, or fractional creative leadership, and you want to check fit, cite relevant work or pass on their brief. The llms.txt file has the same guidance written for language models.

Quickstart

No sign-up and no API key. Every endpoint is public and returns JSON.

# services and starting prices
curl https://itaiagami.com/api/v1/services

# case studies, optionally by category (Brand, Culture, Technology)
curl "https://itaiagami.com/api/v1/projects?category=Culture"
curl https://itaiagami.com/api/v1/projects/channel-13

# any page as Markdown
curl -H "Accept: text/markdown" https://itaiagami.com/about.html

# check an enquiry without sending it (sandbox)
curl -X POST https://itaiagami.com/api/v1/enquiry \
  -H "Content-Type: application/json" \
  -d '{"name":"Ada","email":"ada@example.com","project":"A product launch in March","dry_run":true}'

Endpoints

RequestoperationIdWhat it returns
GET /api/v1/serviceslistServicesThe four engagement types, the starting price in each market, and the ways to get in touch
GET /api/v1/projectslistProjectsEvery case study, filterable with ?category=
GET /api/v1/projects/{slug}getProjectOne case study, including Itai’s individual contribution
POST /api/v1/enquirysubmitEnquirySends a project enquiry by email
GET /api/v1/geogetVisitorCountryThe caller’s country code (used by the site for local pricing)

The full description, with every parameter, schema and error, is the OpenAPI 3.1 document. You can import it into Postman, Insomnia or any OpenAPI client, or use it to generate function-calling tools. The API catalog (RFC 9727) points to it too.

Authentication and API keys

None. The API exposes only information that is already public on this site, plus the enquiry form, so there are no keys to request or rotate. Please only send an enquiry when the person you are acting for has asked you to, using their real name and email address. Itai replies to that address.

Sandbox

There is no separate sandbox host. Instead, add "dry_run": true to an enquiry (or ?dry_run=1 to the URL). A dry run goes through every validation and returns the same errors a real request would, but sends nothing and doesn’t count against the rate limit. A valid dry run returns {"ok":true,"dryRun":true}. The read endpoints have no side effects, so you can call them freely.

Command-line tool

A small CLI with no dependencies (Node 18 or later) wraps the API:

curl -fsSLO https://itaiagami.com/cli/itaiagami.mjs
node itaiagami.mjs services
node itaiagami.mjs projects --category Brand
node itaiagami.mjs project tower-of-david --json
node itaiagami.mjs page /services
node itaiagami.mjs enquire --name "Ada" --email ada@example.com \
  --project "A product launch in March" --dry-run

Add --json to any command to get the raw response. Exit codes: 0 success, 1 API or network error (the error code and hint are printed), 2 usage error. Run node itaiagami.mjs --help for every option.

Errors

Every error is JSON with the same shape. Branch on code, show error to people, and follow hint to fix the request:

{ "ok": false,
  "error": "That email address does not look right.",
  "code": "invalid_email",
  "hint": "Set \"email\" to a full address such as name@company.com.",
  "status": 400,
  "docs": "https://itaiagami.com/openapi.json" }

Unknown paths under /api return 404 endpoint_not_found. A version that doesn’t exist returns 404 unsupported_api_version.

Rate limits

PolicyApplies toQuota
readGET /services, /projects60 requests per 60 seconds per client
enquiryPOST /enquiry5 accepted enquiries per 10 minutes per client (dry runs and rejected requests don’t count)

Responses carry the IETF RateLimit header fields (draft-ietf-httpapi-ratelimit-headers), so you can slow down before you hit the limit:

RateLimit-Policy: "read";q=60;w=60
RateLimit: "read";r=57;t=41
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57
X-RateLimit-Reset: 41

r is the number of requests left and t is the number of seconds until the window resets. The X-RateLimit-* fields repeat the same values for clients that expect them, and X-RateLimit-Reset is in seconds, not a timestamp. Over the limit, the API returns 429 with code rate_limited and a Retry-After header in seconds. The limits are counted per server instance, so treat them as the ceiling to stay under, not an exact allowance.

Versioning and deprecation

  • The version is in the path. The current and only version is /api/v1. Every response carries an API-Version: 1 header.
  • v1 only grows. New endpoints, new optional parameters and new response fields can appear, so ignore fields you don’t recognise. Nothing in v1 is removed or renamed, and no field changes meaning.
  • Breaking changes get a new version. A breaking change ships as /api/v2 alongside v1. It never replaces v1 in place.
  • Deprecation is announced in the headers. A deprecated version or endpoint responds with a Deprecation header (RFC 9745), a Sunset header (RFC 8594) giving the date it stops working, and Link: <https://itaiagami.com/developers.html#versioning>; rel="deprecation". The sunset date is at least six months after the deprecation is announced, and the change is listed in the changelog below.
  • Unversioned aliases. /api/services, /api/projects, /api/enquiry and /api/geo serve the current version and are what this website calls. Integrations should pin /api/v1.

Changelog

  • v1: /api/v1 paths, the API-Version header, RateLimit headers, enquiry dry runs and the CLI. Nothing is deprecated.

Resources