Skip to content

#162 · Public API: Schema Access and Issue Event Links for Agents

TLDR: General Availability: Discover how AI agents can now list DAST schemas with signed URLs and jump from any issue to its latest events in one Public API call.

AI agents that drive DAST through Escape's Public API used to lose two hops on the most basic questions: "where's the schema for this profile?" and "what events produced this issue?". Starting today, the profile detail carries the schema's signed URL alongside its metadata, and the issue detail links straight to the latest events from the scan that surfaced it. The CLI ships matching one-command wrappers so an agent can go from profile to schema, or from issue to full request-response evidence, in a single call.

What's New

  • Schemas on the profile detail: GET /v3/profiles/:profileId now returns signedUrl and isActive on every extraAssets[] entry. No more re-fetching each asset just to get a download link.
  • Issue to events link on the issue detail: GET /v3/issues/:issueId now returns latestEventIds (up to five, newest-first, from the issue's last-seen scan) and latestEventsTruncated so agents know when to paginate.
  • One CLI command per intent:
    • escape-cli profiles get-schema <profile-id> prints the active schema's metadata; add -f <file> to download the bytes via the signed URL in the same call.
    • escape-cli profiles upload-schema <profile-id> --file <path> uploads, creates the schema asset, and attaches it to the profile in one shot.
    • escape-cli issues get-with-events <issue-id> hydrates every latest event, including the full request-response Exchange, in a single MCP tool call.

Why It Matters

Customers who drive Escape at scale do it programmatically, and the feedback we hear most often on customer calls is consistent: agents and CI pipelines want handy commands that wrap multiple steps, not granular flows that mirror the database. Getting a schema used to take two round trips per asset. Attaching a freshly uploaded schema to a profile used to take three different surfaces, one of them undocumented. Navigating from an issue to the events that produced it used to require knowing the event IDs up front.

That's fixed. An agent can now go from a profile id to a downloadable schema in one call, and from an issue id to the actual request-response evidence in one MCP tool call. Triage gets shorter. CI jobs get simpler. MCP-powered tools get to answer real questions instead of stitching together two or three lookups.

The changes land on the detail endpoints only. List endpoints stay unchanged, so there's no fan-out on GET /v3/profiles or GET /v3/issues, no per-profile signed-URL minting on list calls, and no surprise cost or exposure bump for callers that page through collections.

How to Get Started

No flag, no toggle, no configuration: both changes are on for every organization.

  • Public API: fetch a profile with GET /v3/profiles/:profileId and read the new signedUrl and isActive fields on each extraAssets[] entry (signedUrl is non-null only for class === 'SCHEMA'). Fetch an issue with GET /v3/issues/:issueId and read latestEventIds and latestEventsTruncated; hydrate each event with GET /v3/events/:id to get the Exchange.
  • CLI: upgrade to the latest escape-cli. The new commands are profiles get-schema, profiles upload-schema, and issues get-with-events. The existing escape-cli issues get table also gains a LATEST EVENTS column.
  • MCP: the Escape MCP server picks up issues_get_with_events automatically, so agents get the one-call hydration path without any configuration.

Compatibility

Scoped to the Public API wire contract and OpenAPI spec.

Hard-breaking changes

None.

Soft-breaking changes

Wire payloads and HTTP status codes are unchanged. Regenerated SDKs and strongly-typed consumers will see new optional fields.

  • GET /v3/profiles/:profileId response: ProfileExtraAsset now includes two additive fields, signedUrl (nullable string, non-null only for class === 'SCHEMA') and isActive (boolean). Regenerated SDKs expose new accessors. Existing hand-written parsers keep working; the fields are additive.
  • GET /v3/issues/:issueId response: IssueDetailed gains two optional fields, latestEventIds (array of opaque string IDs, GraphQL ID scalars, not guaranteed UUIDs, maximum five, newest-first) and latestEventsTruncated (boolean). Because IssueDetailed is reused inside EventDetailed.issues[], strongly-typed SDK consumers of GET /v3/events/:id will see the typed surface widen. The wire payload of GET /v3/events/:id stays byte-identical: the route never sets these fields.

Non-breaking changes

  • List endpoints untouched: GET /v3/profiles and GET /v3/issues return the same payloads as before. The enrichment is deliberately scoped to the single-resource detail endpoints to avoid fan-out.
  • No new routes, no authentication changes, no status-code changes, no new top-level resource group. Schemas remain modeled as assets.

What's Next?

Regular improvements to the Public API and the CLI, guided by what we hear on customer calls.

Learn More

Questions?

Have a question? Reach out on your dedicated support channel (Slack, Microsoft Teams, or whichever channel we've set up with your team), or email us at support@escape.tech.