Update to Wix
Snapshot Oct 26, 2026 · 18:05 UTC · version 14.0.0
Collection source: downloaded plugin package.
Supporting file metadata differs
Supporting file metadata differs
Observed in package metadata. These changes alone do not establish a new customer-facing feature.
Up to 3 plugins free · no card required.
All fields and original values.
Supporting files
Oct 24, 2026 · 12:47 UTC
[{"relative_path":"references/API_SPEC_SEARCH.md","size_in_bytes":11521},{"relative_path":"references/CALLING.md","size_in_bytes":4851},{"relative_path":"references/EXTRACTING.md","size_in_bytes":7821}]
Oct 26, 2026 · 18:05 UTC
[{"relative_path":"references/API_SPEC_SEARCH.md","size_in_bytes":11521},{"relative_path":"references/CALLING.md","size_in_bytes":4800},{"relative_path":"references/EXTRACTING.md","size_in_bytes":7821}]
Compare saved observations
Download comparison JSONSKILL.md text changes
− removed · + added
No SKILL.md text changes between these observations.
Full technical diff · 1 changed fields
changed /included_files
[
{
"relative_path": "references/API_SPEC_SEARCH.md",
"size_in_bytes": 11521
},
{
"relative_path": "references/CALLING.md",
"size_in_bytes": 4851
},
{
"relative_path": "references/EXTRACTING.md",
"size_in_bytes": 7821
}
][
{
"relative_path": "references/API_SPEC_SEARCH.md",
"size_in_bytes": 11521
},
{
"relative_path": "references/CALLING.md",
"size_in_bytes": 4800
},
{
"relative_path": "references/EXTRACTING.md",
"size_in_bytes": 7821
}
]Full snapshot data
{
"description": "Look up the Wix API/SDK documentation to confirm an exact endpoint, HTTP method, request/response shape, field, enum, or error before writing Wix code — never guess a Wix API from memory. A lookup is a short flow: find the right page, then read it. Two ways: (1) plain `curl` (zero dependencies) — find a page by **semantic search** (`POST /mcp-docs-search/v1/docs/search`, natural-language `{ search_term, document_type(s) }`, incl. the SKILLS recipe corpus for multi-step workflows) **or by browsing** a docs portal as a menu — a structured, typed, counted browse of the REST, SDK, CLI, Build Apps, and Headless portals (`POST /mcp-docs-search/v1/docs/menu/browse`), or the `.md` menu tree from the `llms.txt` root for any surface — then read the page by appending `.md` to its URL; (2) the Wix MCP doc tools when present. Triggers: look up a Wix API, find the Wix endpoint/method, confirm a Wix request body or field, verify a Wix API shape, explore Wix docs, which Wix API do I call, read a Wix method schema.",
"included_files": [
{
"relative_path": "references/API_SPEC_SEARCH.md",
"size_in_bytes": 11521
},
{
"relative_path": "references/CALLING.md",
"size_in_bytes": 4800
},
{
"relative_path": "references/EXTRACTING.md",
"size_in_bytes": 7821
}
],
"name": "wix-docs",
"skill_md_contents": "---\nname: wix-docs\ndescription: \"Look up the Wix API/SDK documentation to confirm an exact endpoint, HTTP method, request/response shape, field, enum, or error before writing Wix code — never guess a Wix API from memory. A lookup is a short flow: find the right page, then read it. Two ways: (1) plain `curl` (zero dependencies) — find a page by **semantic search** (`POST /mcp-docs-search/v1/docs/search`, natural-language `{ search_term, document_type(s) }`, incl. the SKILLS recipe corpus for multi-step workflows) **or by browsing** a docs portal as a menu — a structured, typed, counted browse of the REST, SDK, CLI, Build Apps, and Headless portals (`POST /mcp-docs-search/v1/docs/menu/browse`), or the `.md` menu tree from the `llms.txt` root for any surface — then read the page by appending `.md` to its URL; (2) the Wix MCP doc tools when present. Triggers: look up a Wix API, find the Wix endpoint/method, confirm a Wix request body or field, verify a Wix API shape, explore Wix docs, which Wix API do I call, read a Wix method schema.\"\n---\n\n# Wix Docs — look up the Wix API/SDK documentation\n\nGet the **exact** truth about a Wix API — endpoint, HTTP method, request/response body, a field, an\nenum, or an error. **Never invent a Wix endpoint, path, body, or enum from memory** — confirm it\nhere first. That includes the example endpoints in this skill: they illustrate the mechanics and\ngo stale like any snapshot — discover the real contract before you rely on one.\n\nA lookup is a short flow: **find the right page, then read it.** Do it with `curl` (default, below)\nor the Wix MCP doc tools if your agent has them (Lane 2). Either way, route by what you already\nknow:\n\n- **You have a docs URL** → just read it (§2). Don't re-search for a page you can already name.\n- **A multi-step workflow** (\"take a booking from service setup to payment\") → include the **recipe**\n corpus in the search: `document_types: [\"SKILLS\", …]` alongside the API corpus the steps live in\n (§1A). A recipe carries step ordering, cross-step gotchas, and the one bundled endpoint that does\n the whole job — things no single method page states. No relevant recipe comes back → assemble the\n workflow from the verified per-method contracts in the same result set.\n- **One specific operation, field, or enum** → search its API corpus (`REST` / `SDK`), then read or\n schema-check what you land on.\n\n## Lane 1 — `curl` (default)\n\nThe docs are one tree of markdown pages: **append `.md` to any `https://dev.wix.com/docs/…` URL**\nto get that page as markdown. No SDK, no MCP.\n\n### 1. Find the page — search, browse, or query the index\n\nThree ways to reach the right page — use whichever fits.\n\n**A. Semantic search.** Describe what you want in natural language (\"let a customer book an\nappointment\"), not just keywords; hits come back ranked by relevance. Same `POST` body for both\nvariants: `search_term` (required, 1–500), **one** of `document_type` (a single corpus) or\n`document_types` (an array — several corpora in one ranked call); `maximum_results` (1–20, def 15,\ncounted across the combined result set), `lines_in_each_result` (0–200, def 20; `0` = no per-hit\nline cap). Corpora: `REST` (default) · `SDK` · `SKILLS` · `WIX_HEADLESS` · `BUSINESS_SOLUTIONS` ·\n`VELO` · `WDS` · `BUILD_APPS` · `CLI` · `OVERVIEW`. `SKILLS` is the dedicated **recipe corpus** —\nmulti-step workflow pages a single-API search does not return; `OVERVIEW` is platform orientation\n(which development approach, which API family).\n\n**Search the corpora a question actually spans, in one call.** The service ranks them together and\ninterleaves the hits, so they compete on relevance instead of you guessing which to try first —\nand one round trip replaces several. There's no fixed combination: pick by the question. Passing\nboth `document_type` and `document_types` is an error (*\"Pass either document_type or\ndocument_types, not both\"*), and an unknown corpus name is rejected with the valid list.\n\nTwo variants — pick by what you're doing:\n\n**`/docs/search/markdown` → read it (start here).** Returns JSON with a single `content` field\nholding one LLM-ready markdown string (extract it with `jq -r '.content'`) where each hit is a\n**condensed method doc**: the API **endpoint**, **real request code examples**, the **response\nshape**, and the **method description** (with its gotchas). Hits are **previews, not full pages**:\nthe condensed format has fixed per-section limits, so raising `lines_in_each_result` does not expand\nevery section, and `0` only removes the per-hit line cap — it never reproduces the whole source page.\nBefore building on a hit, check sufficiency: do you have the required inputs, the conditions that\napply to your case, and the REST contract or SDK signature you need? If yes, proceed — no extra\nfetch. If not, make **one targeted follow-up**: read the method page (§2) or pull its schema (§C).\n\n```bash\ncurl -sS -X POST 'https://www.wixapis.com/mcp-docs-search/v1/docs/search/markdown' \\\n -H 'Content-Type: application/json' \\\n --data-raw '{\"search_term\":\"create a booking\",\"document_type\":\"REST\",\"maximum_results\":3}' \\\n | jq -r '.content' # no jq? → python3 -c 'import sys,json;print(json.load(sys.stdin)[\"content\"])'\n```\n\nA question that spans a workflow and its individual calls asks for both corpora at once — the\nrecipe and the per-method contracts arrive in one ranked list:\n\n```bash\ncurl -sS -X POST 'https://www.wixapis.com/mcp-docs-search/v1/docs/search/markdown' \\\n -H 'Content-Type: application/json' \\\n --data-raw '{\"search_term\":\"end to end booking flow\",\"document_types\":[\"SKILLS\",\"REST\"],\"maximum_results\":6}' \\\n | jq -r '.content'\n```\n\n**`/docs/search` (JSON) → route on it.** Returns `{ results: [ { title, url, content,\nrelevance_score, kb_name, … } ] }` — structured hits. Use it when you want to **pick/route\nprogrammatically**: grab a hit's `url` to read that page (§2) or feed it to the schema query (§C).\n\n**`kb_name` tells you what each hit is** — every hit carries one, and the kind decides what you can\ndo with it: only a method page has a schema to pull (§C); an article or recipe is read as prose (§2).\n\nThe request can't make that split for you. **A corpus mixes kinds** — searching the API reference\nreturns method pages *and* the prose around them — and no corpus returns method pages alone. So\npick corpora with `document_types`, then separate the kinds on the way out with `kb_name`. Two\nthings not to do instead: don't infer the kind from the presence of a `url` (every hit has one,\narticles and recipes included), and don't infer it from the corpus you asked for.\n\nMost values name their kind (`…_METHODS_…` for method pages, `…_DOCS_…` for prose, `SKILLS_KB_ID`\nfor recipes) but not all do — the SDK's method index is `API_REFERENCE_SDK_KB_ID`. So list the\nlabels your search actually returned, then act on those, rather than pattern-matching the name or\nhard-coding a list of ids.\n\n```bash\n# see what came back — label, title, url\ncurl -sS -X POST 'https://www.wixapis.com/mcp-docs-search/v1/docs/search' \\\n -H 'Content-Type: application/json' \\\n --data-raw '{\"search_term\":\"end to end booking flow\",\"document_types\":[\"REST\",\"SKILLS\",\"WIX_HEADLESS\"],\"maximum_results\":10}' \\\n | jq -r '.results[] | \"\\(.kb_name)\\t\\(.title)\\t\\(.url)\"'\n# no jq? → python3 -c 'import sys,json;[print(r.get(\"kb_name\"),r[\"title\"],r.get(\"url\")) for r in json.load(sys.stdin)[\"results\"]]'\n\n# then take the kind you need, by the label you just saw\n… | jq -r '.results[] | select(.kb_name == \"REST_METHODS_KB_ID\") | \"\\(.title)\\t\\(.url)\"'\n```\n\n**B. Browse the docs tree as a menu.** Two ways: the **structured browse endpoint** for the\nsupported portals (preferred there — typed, counted, filterable), and the **`.md` menu tree** for\nany surface and for reading pages.\n\n**B1. Structured browse — the supported portals.** `POST /mcp-docs-search/v1/docs/menu/browse`\nwalks a portal's tree and returns each child with its **kind**, its **HTTP verb** (for methods), and\n**subtree counts** (\"Catalog V3 — 121 methods, 32 articles\"), so you pick the right area by shape —\nin ~2 KB, not a ~40 KB menu page you have to `grep`. `include`, `name_filter`, and `depth` jump\nstraight to what you want.\n\nPortals (`document_type`): `REST` (default — the `api-reference` portal) · `FRONTEND_SDK` (`sdk`) ·\n`CLI` (`wix-cli`) · `BUILD_APPS` (`build-apps`) · `WIX_HEADLESS` (`go-headless`). In **browse only**,\n`SDK` is an alias for `REST` (the API reference documents both views on every page) — it does **not**\nselect `FRONTEND_SDK`, and the alias doesn't apply to semantic search. To discover a portal's areas,\nomit `menu_url` — you get the portal root; passing a supported portal's URL as `menu_url` also infers\nthe portal for you.\n\nBody: `menu_url?` (absolute docs URL; omit for the portal root), `document_type?`, `depth?` (1, max\n6), `include?` (`CATEGORY`·`RESOURCE`·`METHOD`·`ARTICLE`·`WEBHOOK`·`OBJECT`·`SKILL`), `deprecated?`\n(`HIDE` default·`SHOW`·`ONLY`), `name_filter?`, `max_nodes?`, `format?` (`MARKDOWN` default →\n`content` string; `STRUCTURED` → JSON tree with `url`/`http_method`/`resource_id`/`child_counts`,\nplus `counts_by_type`, `truncated`, `deprecated_counts_by_type`).\n\nTwo response signals to act on, not ignore:\n\n- **`truncated: true`** — the node cap cut the listing. Narrow instead of re-reading: browse a\n deeper `menu_url`, tighten `include`/`name_filter`, or lower `depth`.\n- **Deprecation filtering** — deprecated entries are **hidden by default**;\n `deprecated_counts_by_type` reports how many were filtered out. An API missing from a browse may\n be deprecated, not nonexistent — re-browse with `deprecated: \"SHOW\"` (or `\"ONLY\"`) to inspect it,\n and follow its replacement pointer where one is documented.\n\n```bash\n# a vertical's structure, with per-child subtree counts\ncurl -sS -X POST 'https://www.wixapis.com/mcp-docs-search/v1/docs/menu/browse' \\\n -H 'Content-Type: application/json' \\\n --data-raw '{\"menu_url\":\"https://dev.wix.com/docs/api-reference/business-solutions/stores\"}' \\\n | jq -r '.content'\n\n# jump straight to a method by name — no multi-level grep\ncurl -sS -X POST 'https://www.wixapis.com/mcp-docs-search/v1/docs/menu/browse' \\\n -H 'Content-Type: application/json' \\\n --data-raw '{\"menu_url\":\"https://dev.wix.com/docs/api-reference/business-solutions/bookings\",\"include\":[\"METHOD\"],\"name_filter\":\"cancel\",\"depth\":4}' \\\n | jq -r '.content'\n\n# a non-REST portal: the CLI docs, from the portal root\ncurl -sS -X POST 'https://www.wixapis.com/mcp-docs-search/v1/docs/menu/browse' \\\n -H 'Content-Type: application/json' \\\n --data-raw '{\"document_type\":\"CLI\",\"depth\":2}' | jq -r '.content'\n```\n\nBrowse-only: it hands you the page **URL** — read it by appending `.md` (§2), and get the exact\nschema from §C.\n\n**B2. `.md` menu tree — any surface, and how you read pages.** Every docs path has a `.md` twin, so\nyou can navigate any surface with zero dependencies; use it for surfaces structured browse doesn't\ncover (e.g. Velo) and to read leaves. `curl https://dev.wix.com/docs/llms.txt` is the\ntop-level map; the portals under it:\n\n| Portal | Start here for |\n|---|---|\n| [`api-reference.md`](https://dev.wix.com/docs/api-reference.md) | **All backend / business-solution APIs — the main one.** Each page documents **both** its REST and SDK usage (`.md?apiView=SDK` for the SDK view). |\n| [`sdk.md`](https://dev.wix.com/docs/sdk.md) | **SDK-only surfaces not in the API reference:** client setup (`createClient`, `OAuthStrategy`), core modules (`@wix/sdk`, `@wix/essentials`), host modules (`dashboard`/`editor`/`site`), and frontend modules (`members`, `pay`, `seo`, `storage`, `pricing-plans`, …). |\n| [`go-headless.md`](https://dev.wix.com/docs/go-headless.md) | Headless setup, auth, hosting, framework integration. |\n| [`build-apps.md`](https://dev.wix.com/docs/build-apps.md) | Building Wix apps / extensions. |\n| [`wix-cli.md`](https://dev.wix.com/docs/wix-cli.md) · [`velo.md`](https://dev.wix.com/docs/velo.md) | Wix CLI commands; Velo site-coding APIs. |\n\n**Drill like a menu** — append `.md` to any path (a *section* → a menu of child links, a *leaf* →\nthe content/method page); truncate to go up, extend to go down. **Read the sibling intro / \"About …\"\n/ flow articles too**, not just the method page. Example — drill to the create-booking method,\ngrepping each menu for the next link:\n\n```bash\ncurl -sS https://dev.wix.com/docs/api-reference/business-solutions.md | grep -i bookings # → .../bookings.md\ncurl -sS https://dev.wix.com/docs/api-reference/business-solutions/bookings.md | grep -iE 'bookings|flow' # → resource/flow pages\ncurl -sS https://dev.wix.com/docs/api-reference/business-solutions/bookings/bookings.md | grep -i create # → the create method leaf\ncurl -sS https://dev.wix.com/docs/api-reference/business-solutions/bookings/bookings/bookings-writer-v2/create-booking.md # read it\n```\n\nA 2-level map of the API-reference portal (all verticals, one level down) is in\n`references/EXTRACTING.md`.\n\n**C. Query the API index — one call, structured.** The `code-mode` search endpoint runs a JS\nfunction over `lightIndex` (the whole REST API spec: every resource + method with `operationId`,\n`httpMethod`, `menuPath`, `docsUrl`, and executable `publicUrl`). Best when you want to\n**enumerate/filter methods programmatically** — browse a vertical, or grep across *all* methods —\nand get the `docsUrl` + `publicUrl` back in one shot, no menu-drilling:\n\n```bash\n# pinpoint a method by keyword across the whole index → its docsUrl + executable publicUrl\ncurl -sS -X POST 'https://mcp.wix.com/api/code-mode/search' -H 'Content-Type: application/json' \\\n --data-raw '{\"code\":\"async function(){ return lightIndex.flatMap(r=>r.methods).filter(m=>/createBooking$/i.test(m.operationId)).map(m=>({op:m.operationId, httpMethod:m.httpMethod, publicUrl:m.publicUrl, docsUrl:m.docsUrl})); }\"}'\n```\n\n**Filter narrowly and return only the fields you need** — the index is large, so an unfiltered dump\nis huge. Scope: the **REST surface**. `lightIndex` indexes REST **methods**; a sibling `articles`\nindex plus `getArticleContentByUrl(docsUrl)` / `getArticleContent(resourceId)` cover the REST\nportal's **prose** (introductions, recipes, flow pages). SDK-only surfaces and the other portals\naren't here — use A/B for those, and note the schemas returned are REST contracts, not SDK\nsignatures (the SDK view of the same method lives on its docs page, §2). More examples (browse a\nvertical, `menuPath` walk, resource schema) and the schema/article readers →\n**`references/API_SPEC_SEARCH.md`**.\n\nIf the Wix MCP is present, it exposes these same capabilities as native tools (no `curl`/JSON\nboilerplate) — Lane 2.\n\n### 2. Read what you land on\n\nAppending `.md` to a URL gives one of **three kinds of page**. Know which you're looking at, and\nhandle it accordingly:\n\n- **Menu page** — a *section* path (from browsing, §1B). A list of child links, often tens of KB —\n **don't read it whole; `grep` it** for the child you want, then drill into that page:\n\n ```bash\n curl -sS 'https://dev.wix.com/docs/api-reference/business-solutions/bookings.md' | grep -i 'booking'\n ```\n\n- **Article / guide** — introductions, concepts, sample-flow pages. Prose markdown, usually small —\n **read it whole**:\n\n ```bash\n curl -sS 'https://dev.wix.com/docs/api-reference/business-solutions/bookings/bookings/introduction.md'\n ```\n\n- **Method page** — one API method, and the heavy one: it carries **both** a REST and a JavaScript\n SDK section, the full request/response schema, and code examples — often 100 KB+. **Don't swallow\n the whole page** — map it, then pull the part you need (the examples are usually enough to model a\n call):\n\n ```bash\n curl -sS \"$URL.md\" | grep -nE '^#{1,3} ' # 1. map the outline\n curl -sS \"$URL.md\" | awk '/^## REST API/{r=1} r&&/^### Examples/{f=1} /^## JavaScript SDK/{f=0} f' # 2. just the REST examples\n curl -sS \"$URL.md\" | grep -nE 'name: (selectedPaymentOption|totalParticipants)' # 3. grep specific schema fields\n ```\n\n More recipes (split REST vs SDK, resolve an enum) → `references/EXTRACTING.md`.\n\n For the exact **structured** schema and enum values, don't hand-slice the markdown — query the API\n spec with a `curl` `POST` to `https://mcp.wix.com/api/code-mode/search` (the no-MCP equivalent of\n the MCP `SearchWixAPISpec`). The `code` is a JS function with `lightIndex` and\n `getResourceSchemaByUrl(docsUrl)` in scope; return only what you need.\n\n `getResourceSchemaByUrl` scopes to the URL you pass: a **method URL** returns a schema whose\n `methods` array holds just that method — read it as `methods[0]`, and don't select it by comparing\n `m.docsUrl` to your input (the reader normalizes URLs). A **resource URL** (the method URL minus\n its last segment) returns the **whole resource** — fetch that when you need sibling operations or\n shared resource context.\n\n ```bash\n # find a method by keyword → its docsUrl + executable publicUrl\n curl -sS -X POST 'https://mcp.wix.com/api/code-mode/search' -H 'Content-Type: application/json' \\\n --data-raw '{\"code\":\"async function(){ return lightIndex.flatMap(r=>r.methods).filter(m=>/createBooking$/i.test(m.operationId)).map(m=>({op:m.operationId, httpMethod:m.httpMethod, publicUrl:m.publicUrl, docsUrl:m.docsUrl})); }\"}'\n\n # a METHOD URL → that one method's contract (resolve $circular refs via s.components.schemas)\n curl -sS -X POST 'https://mcp.wix.com/api/code-mode/search' -H 'Content-Type: application/json' \\\n --data-raw '{\"code\":\"async function(){ const s=await getResourceSchemaByUrl(\\\"https://dev.wix.com/docs/api-reference/business-solutions/bookings/bookings/bookings-writer-v2/create-booking\\\"); const m=s.methods[0]; return { publicUrl:m.publicUrl, requestBody:m.requestBody, responses:m.responses }; }\"}'\n ```\n\n The envelope is `{ \"result\": … }` or `{ \"error\": \"<message>\" }` — **both arrive as HTTP 200**, so\n check the body, not the status. The error text names the fix: an article URL → switch to\n `getArticleContentByUrl`; an unknown URL → search `lightIndex` by keyword. Don't re-send an\n identical failed lookup — change something based on the error, and if discovery still fails,\n report the limitation instead of guessing the contract.\n\n Full example set (resource listing, partial-URL resolution, enum/nested-ref expansion) →\n `references/API_SPEC_SEARCH.md`.\n\n## Lane 2 — Wix MCP doc tools (only if your agent has them)\n\nIf the Wix MCP is connected, these are the **same backends as Lane 1** (the doc-search service and\nthe API-spec index) wrapped as native tools — schema-validated, response-size handled, no\n`curl`/JSON boilerplate. A convenience over the curl lane, **not a richer data source**; use them\nwhen present, fall back to Lane 1 when not. Optional — skip this lane if the tools aren't present.\n\n| Tool | Use for |\n|---|---|\n| `SearchWixRESTDocumentation` | Find a REST method/recipe by keyword |\n| `SearchWixSDKDocumentation` | Find an SDK method (surfaces runtime functions a module menu hides) |\n| `SearchWixAPISpec` → `getResourceSchemaByUrl` | Structured schema — a **method URL** for that method's contract, a **resource URL** for the whole resource |\n| `ReadFullDocsArticle` | Read a recipe/flow/article page in full |\n| `BrowseWixRESTDocsMenu` | Walk the menu tree to drill to a method |\n\n- **Fetch the method for its contract; fetch the resource for context.** A method URL gives exactly\n that method. When a requirement may live on a *sibling* method (e.g. a `memberId` required on\n single-create but omitted from the bulk-create page), fetch the **resource** URL instead — the\n resource view carries every method plus the shared object schema.\n- The **recipe-first routing** at the top of this skill applies here too: for a multi-step workflow,\n search the recipe corpus (many verticals publish recipes under a\n `…/business-solutions/<vertical>/skills` node) before assembling per-method calls.\n\n## The `.md` suffix\n\nAppend `.md` only when `curl`-ing a page directly. The MCP tools and the search endpoint take the\nplain docs URL **without** `.md` — never feed a `.md` URL to an MCP tool.\n\n## From docs to calls\n\nUnderstanding the contract is this skill's job; executing it needs an identity. Which identities a\nmethod accepts is part of what you read — check the method page's permissions and identity notes\nbefore calling, and confirm your token's site/account scope matches. Token minting (CLI admin\ntokens, visitor tokens), the identity model, and the dynamic site-context report →\n**`references/CALLING.md`**.\n\n## Before you write the code\n\nConfirm on the page — not from memory — the endpoint, the HTTP verb, the request body shape,\nrequired fields, and any enum values. Then write the call. If you're extending a skill's shipped\nclient, keep the skill's existing transport/helper style; you're adding one call, not\nre-architecting.\n"
}SHA-256 of public snapshot: ad76d2e02a1552ca89916264e08cddd92ad74572fff78a9c7577d19908726eaa