Skip to content

Add a Grupo Éxito Marketplace adapter with list-valued token paths - #1570

Merged
helpcodeai merged 1 commit into
mainfrom
feat/exito-marketplace-adapter
Nov 7, 2026
Merged

helpcodeai merged 1 commit into
mainfrom
feat/exito-marketplace-adapter

Conversation

@helpcodeai

Copy link
Copy Markdown
Contributor

Summary

This adds a Grupo Éxito Marketplace adapter: the seller API of exito.com and Éxito's other sites in Colombia, documented at https://developers.exito.com/. It also adds one opt-in LOGIN_TOKEN option.

How the API works:

  • It is split over seven AWS API Gateway addresses (*.execute-api.us-east-1.amazonaws.com, -pdn stages). Each tool carries its documented absolute URL.
  • Calls send a Cognito token bare in Authorization (the docs write COGNITO_TOKEN) and an x-api-key.
  • Éxito gives sellers the token request (username + password + x-api-key) in private instructions; the public docs never describe it. The adapter therefore uses LOGIN_TOKEN with the token address as a connector variable (EXITO_LOGIN_URL, the same precedent as DOCUWARE_TOKEN_URL).

Changes

Engine (login-token.service.ts, opt-in)

  • tokenJsonPath may be a list of paths, tried in order; the first non-empty string is the token. "." takes a bare-string answer.
  • A single string behaves exactly as before.
  • The error names every path, or quotes the service's refusal as before.
  • Kept in line: catalog.spec.ts (well-formed check), scripts/probe-keyless.mjs, docs/connectors/login-token-auth.md, docs/tool-definition.md.

Adapter intl/exito-marketplace.json (category e-commerce), 16 tools:

  • Reads (on):
    • products;
    • the moderation queues: waiting for approval, rejected with reason, pending the seller's decision;
    • bulk upload status;
    • categories (all / one) and category features;
    • orders;
    • payout statements (bills).
  • Writes (on):
    • create products (JSON array, up to 400 EANs, images by URL, features);
    • products with offers;
    • upsert offers;
    • price/stock for one EAN.
  • Writes (off at install): order tracking and invoice upload.
  • Not built:
    • the shipping label: its documented route exists only on a /dev stage, and the prod route answers "Missing Authentication Token";
    • the seller-hosted notifyproduct / notifyoffer callbacks;
    • delete: no such endpoint, so stock 0 is the way to stop selling.

Other details:

  • Credentials: EXITO_USERNAME, EXITO_PASSWORD (secret), EXITO_API_KEY (secret, sent as x-api-key on the login and on every call), EXITO_LOGIN_URL, EXITO_SELLER_ID (numeric idSeller, required by the moderation queues and bills).
  • Auth: tokens are kept 1 h (the Cognito default), renewed early, and the engine logs in again on a 401.
  • errorWhen: a non-empty errors / Errors list inside HTTP 200 → a failed call. Batch results with per-EAN messages are left to the model, and the descriptions say to read them.
  • The instructions explain the asynchronous moderation flow and the offer rules: price above 8000 COP; IsUpdatedStock; more than 30% → PEX / PriceApproval; up to 1 h of indexing; up to 4 h of site cache.
  • Logo exito.svg: the public-domain (trademarked) mark from Wikimedia Commons, Inkscape metadata stripped. Catalog regenerated, counts 713 → 714, llms.txt regenerated.

Cloud and self-hosted: identical in both. The token address is a user-supplied URL and passes through the SSRF guard on both; the token is cached encrypted in connector_auth_cache.

Not yet verified with real credentials. The token request's body field names (username/password assumed) and response shape (Cognito AuthenticationResult.IdToken tried first, then the usual alternatives) come from no public document. If the seller's instructions differ, it is a one-line adapter change.

Type

  • New feature (adapter + opt-in engine option)

Testing

  • Added/updated unit tests

In packages/backend (after npx prisma generate):

  • npx jest --maxWorkers=4 src/connectors/engines/login-token.service.spec.ts: 78 passed (7 new for the list form).

  • npx jest --maxWorkers=4 src/adapters/intl/exito-marketplace: 14 passed, 1 live block skipped. The spec runs the real RestEngine + LoginTokenService with axios mocked and checks:

    • the login request (x-api-key, body);
    • the bare token + x-api-key on calls, and token reuse;
    • a new login after a 401;
    • every tool's URL, method, enabled flag and readOnly annotation;
    • query and body shapes;
    • errorWhen against the documented 200 bodies.

    Live: RUN_EXITO_LIVE=1 (or RUN_EXITO_MARKETPLACE_LIVE=1) with the five EXITO_* variables, read-only.

  • npx jest --maxWorkers=4 on catalog.spec, env-var-meta, env-var-checks, setup-guide, catalog-summary, catalog-search, instruction-facts, connector-setup.service, probe.util, adapters.service, mcp-adapter, login-token and rest.engine*: 26 suites, 16,099 tests passed.

  • npx jest --maxWorkers=4 on the specs of all 38 LOGIN_TOKEN adapters + connector-setup-status: 39 suites, 385 passed, 55 skipped (live).

  • npx tsc --noEmit -p tsconfig.json: no errors.

  • npm run lint: 0 errors, 11 warnings, all in files this PR does not touch. It rewrote nothing.

From the repo root:

  • node scripts/validate-adapters.mjs --warn: 730 passed. The warning total is the same as on main (1440), so there are none for the new adapter.
  • node scripts/regenerate-catalog.mjs: 730 adapters.
  • node scripts/adapter-count.mjs --check: OK, 714 adapters.
  • node scripts/generate-llms-txt.mjs --check: up to date.
  • node scripts/generate-cli-operations.mjs --check: up to date.
  • node --test scripts/validate-adapters.test.mjs scripts/adapter-new.test.mjs scripts/generate-llms-txt.test.mjs: 60 passed.
  • node --test scripts/satellites/satellites.test.mjs: 18 passed.

Frontend: only an SVG is added, so the frontend lint, typecheck and Playwright were not run.

Against the real hosts, with no credentials sent:

  • Every documented route answers 401 {"message":"Unauthorized"} (it exists behind the Cognito authorizer). Unknown routes answer 403 Missing Authentication Token.
  • The categories host answers 403 Forbidden for every path, which is API Gateway's missing-API-key answer. That is why x-api-key goes on every call.

Checklist

  • My code follows the existing code style
  • I have tested my changes locally
  • I have updated documentation (if applicable)
  • This PR has a descriptive title

Grupo Éxito's marketplace seller API (Colombia, developers.exito.com)
sits behind several API Gateway addresses with a Cognito authorizer:
calls send the token bare in Authorization, plus an x-api-key. The
token request (username, password, x-api-key) is not published, so the
adapter takes its address as EXITO_LOGIN_URL and uses LOGIN_TOKEN.

LOGIN_TOKEN gains one opt-in option for logins whose answer is not
documented: tokenJsonPath may list several paths, tried in order; the
first non-empty string is the token. A single path works as before.

The adapter has 16 tools: products and their moderation queues (waiting,
rejected, pending the seller's decision), the bulk upload status,
categories and their specifications, orders and payout statements,
creating products with image URLs and features, products with offers,
and offers (price and stock, also for one EAN). Order tracking and
invoice upload are installed switched off. The documented sticker route
only exists on a dev stage and is left out.
@helpcodeai
helpcodeai requested a review from D3nisty as a code owner November 7, 2026 08:53
@helpcodeai
helpcodeai merged commit 917d9ca into main Nov 7, 2026
18 checks passed
@helpcodeai
helpcodeai deleted the feat/exito-marketplace-adapter branch November 7, 2026 09:13
@github-actions github-actions Bot locked and limited conversation to collaborators Nov 7, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant