DEV Community

Peter
Peter

Posted on

Valid JSON, broken discovery: the UCP checks that should fail your build

If your /.well-known/ucp file is valid JSON but Google AI Mode or other UCP agents still cannot use it, you do not have a formatting problem.

You have a discovery problem.

That distinction matters.

In our Apr 1, 2026 scan of 28 stores, 26 were broken or missing and 2 were unreachable. That means 92% failed before richer commerce capabilities even mattered. We also found 0 fully healthy profiles. The pattern was consistent: merchants are debating payment rails and optional capability coverage while basic UCP discovery is still broken.

This article covers the UCP checks that should fail your build - not warn, not get buried in a dashboard, but stop a deploy until fixed.

Discovery comes before checkout

UCP and ACP solve different problems.

  • UCP is how Google AI Mode, Gemini, and other UCP-compatible agents discover a merchant and learn which commerce services it exposes.
  • ACP is OpenAI and Stripe's protocol for delegated payment and ChatGPT commerce flows.

So the implementation order for most merchants is simple:

  1. Make /.well-known/ucp fetchable
  2. Make service endpoints callable over HTTPS
  3. Add signing keys so integrations can verify trust boundaries
  4. Then worry about payment handlers and ACP-specific checkout rails if your channel mix needs them

If step 1 fails, nothing later matters.

The checks that should fail your build

These are the issues I would treat as build-breaking in CI.

1. /.well-known/ucp is missing or not fetchable

This is the most obvious blocker and still the most common one.

From the Apr 1 scan, multiple domains scored F because of UCP_FETCH_FAILED. No manifest means no discovery. An agent cannot negotiate capabilities with a merchant it cannot find.

Quick repro:

curl -i https://example.com/.well-known/ucp
Enter fullscreen mode Exit fullscreen mode

What should fail the build:

  • 404 or 403 response
  • redirect loop
  • HTML page instead of JSON
  • timeout or TLS failure

What good looks like:

  • direct HTTPS URL
  • 200 response
  • JSON body

2. Endpoint URLs are not HTTPS

UCP requires HTTPS for transport. If your manifest points to an http:// endpoint, that is not a soft warning.

That is a broken integration.

Example of a bad service definition:

{
  "ucp": {
    "version": "2026-01-11",
    "services": {
      "dev.ucp.shopping": {
        "version": "2026-01-11",
        "spec": "https://ucp.dev/specification/shopping/",
        "rest": {
          "schema": "https://ucp.dev/services/shopping/rest.openapi.json",
          "endpoint": "http://store.example.com/api/ucp"
        }
      }
    },
    "capabilities": []
  }
}
Enter fullscreen mode Exit fullscreen mode

Fix it by serving the endpoint over HTTPS only:

"endpoint": "https://store.example.com/api/ucp"
Enter fullscreen mode Exit fullscreen mode

Related validator rule:

  • UCP_ENDPOINT_NOT_HTTPS

3. Endpoint URLs have a trailing slash mismatch

This looks minor. It is not.

The UCP reference guidance says endpoint URLs should not use trailing slashes. In practice, trailing slash mismatches create annoying agent and proxy bugs, especially when paths are concatenated into checkout routes like /checkout-sessions.

Bad:

"endpoint": "https://store.example.com/api/ucp/"
Enter fullscreen mode Exit fullscreen mode

Safer:

"endpoint": "https://store.example.com/api/ucp"
Enter fullscreen mode Exit fullscreen mode

Related validator rule:

  • UCP_ENDPOINT_TRAILING_SLASH

This should fail CI because it is the kind of issue that passes visual review and still breaks requests later.

4. ucp.version is missing or malformed

UCP uses date-based versioning.

Current stable version in the reference docs:

2026-01-11
Enter fullscreen mode Exit fullscreen mode

If your file omits ucp.version or uses the wrong format, agents cannot reliably interpret your profile.

Bad:

{
  "ucp": {
    "services": {},
    "capabilities": []
  }
}
Enter fullscreen mode Exit fullscreen mode

Also bad:

{
  "ucp": {
    "version": "v1",
    "services": {},
    "capabilities": []
  }
}
Enter fullscreen mode Exit fullscreen mode

Good:

{
  "ucp": {
    "version": "2026-01-11",
    "services": {},
    "capabilities": []
  }
}
Enter fullscreen mode Exit fullscreen mode

Related validator rules:

  • UCP_MISSING_VERSION
  • UCP_INVALID_VERSION_FORMAT

5. The root ucp object is missing

A surprising number of machine-readable files are still structurally wrong in basic ways.

If the root ucp object is missing, the profile is not a UCP profile.

Bad:

{
  "version": "2026-01-11",
  "services": {},
  "capabilities": []
}
Enter fullscreen mode Exit fullscreen mode

Good:

{
  "ucp": {
    "version": "2026-01-11",
    "services": {},
    "capabilities": []
  }
}
Enter fullscreen mode Exit fullscreen mode

Related validator rule:

  • UCP_MISSING_ROOT

This is exactly the kind of issue validators should catch instantly and CI should block.

6. Namespace authority and schema origins do not match

UCP uses reverse-domain namespaces for capabilities and services. The schema origin needs to line up with namespace authority.

If it does not, you create ambiguity and trust problems.

Related validator rule:

  • UCP_NS_ORIGIN_MISMATCH

This is not just tidiness. It is part of how UCP avoids spoofing and keeps capability ownership clear.

7. Signing keys are missing

This is one of the most important examples of a check teams incorrectly downgrade to a warning.

In our Apr 1 scan, several C-grade profiles had a live manifest but were still missing signing keys, including allbirds.com, gymshark.com, kyliecosmetics.com, fashionnova.com, colourpop.com, brooklinen.com, and chubbiesshorts.com.

Those stores are ahead of merchants with no manifest at all. But missing signing keys is still serious because UCP integrations rely on cryptographic verification for trust-sensitive flows like webhook verification.

Related validator rule:

  • UCP_MISSING_SIGNING_KEYS

Minimal JWK example:

"signing_keys": [
  {
    "kid": "key-1",
    "kty": "EC",
    "crv": "P-256",
    "x": "...",
    "y": "...",
    "use": "sig",
    "alg": "ES256"
  }
]
Enter fullscreen mode Exit fullscreen mode

If your team is deciding what fails CI and what only warns, this belongs in the fail bucket.

What should warn instead of fail

Not every UCP issue should block a deploy.

This is where teams overreact.

Google's merchant guidance makes it clear that capabilities are merchant-selected. That means optional capability gaps should not automatically be treated the same way as discovery failures.

For example:

  • missing optional capability coverage
  • extension drift
  • richer cart or catalog support not yet implemented

Those can be warnings.

The validator should separate:

  • discovery-critical blockers
  • trust and endpoint correctness blockers
  • optional capability drift
  • non-UCP site quality hints such as Schema.org organization or return policy gaps

That severity split is the difference between a validator developers trust and a noisy checklist they ignore.

A practical CI workflow

A good UCP validation job should do three things:

  1. return stable rule IDs
  2. print copy-paste repro commands
  3. emit machine-readable JSON for diffs and pull request checks

Example shell step:

curl -sS https://example.com/.well-known/ucp | jq .
Enter fullscreen mode Exit fullscreen mode

Example policy:

  • fail on UCP_FETCH_FAILED
  • fail on UCP_ENDPOINT_NOT_HTTPS
  • fail on UCP_ENDPOINT_TRAILING_SLASH
  • fail on UCP_MISSING_VERSION
  • fail on UCP_INVALID_VERSION_FORMAT
  • fail on UCP_MISSING_ROOT
  • fail on UCP_NS_ORIGIN_MISMATCH
  • fail on UCP_MISSING_SIGNING_KEYS
  • warn on optional capability gaps
  • warn on non-blocking metadata issues

That keeps your build focused on what actually breaks discovery and callable commerce.

Where ACP fits

ACP still matters.

But only after discovery works.

ACP is about delegated payment and ChatGPT-oriented commerce flows. It has its own requirements, such as checkout endpoints, product feeds, and payment handler readiness. It is a separate implementation track from hosting a correct UCP manifest for Google and other UCP agents.

So if your team is debating whether to spend this sprint on Stripe delegated payment support or on fixing /.well-known/ucp, the answer for most merchants is:

Fix UCP discovery first.

Payments headlines are louder.

Discovery bugs are what actually keep you invisible.

Final takeaway

Valid JSON is not the bar.

Discoverable, trustworthy, callable UCP is the bar.

The fastest way to improve merchant readiness is to stop treating discovery blockers like low-priority lint errors. If an agent cannot fetch your manifest, trust your keys, or call your endpoints over HTTPS, your store is not ready for agentic commerce.

Fail those checks in CI.

Everything else can come after.

Top comments (0)