In ZAP's control API, what do the segments of `/JSON/core/view/version/` mean, and which request types exist?
answer
- the representation is decided first
- four path segments, then parameters
- one of them reads, one writes
- who builds the response body
basics
~10 sFormat first, then component, request type and name. JSON is the response format, core the component, view the request type, version the call. The request types are view, action, other and pconn.
solid answer
~40 sZAP's control API puts the whole call in the path, read positionally as `/<format>/<component>/<reqtype>/<name>/`, with everything else as ordinary request parameters. The **format comes first**, so you pick `JSON`, `XML`, `HTML`, `JSONP` or `UI` by editing the URL rather than by sending an `Accept` header. The component is the prefix a registered implementor claims — `core`, `ascan` and one per add-on that exposes an API. There are four request types: `view` reads, `action` changes state, `other` lets the component write the whole response itself (a report, a certificate), and `pconn` hands it the raw streams so it can hold the connection open. The format segment is upper-cased before it is resolved; the request type and the component are matched exactly.
code
bash · 9 lines# /<format>/<component>/<reqtype>/<name>/
curl --proxy "$ZAP_PROXY" "http://zap/JSON/core/view/version/"
# an action, with its parameters in the query string
curl --proxy "$ZAP_PROXY" \
"http://zap/JSON/ascan/action/scan/?url=https://example.com"
# an 'other' endpoint writes the whole response itself
curl --proxy "$ZAP_PROXY" "http://zap/OTHER/core/other/jsonreport/"go deeper
Recall the order of the four segments and be able to read one aloud: format, component, request type, call name. Know that parameters ride in the query string or a form body, not in the path.
Explain what each request type is for, especially the 'other' type: the component writes the whole response itself, which is how raw bytes such as a report come back. Mention that the format segment is case-tolerant and the rest is not.
Show that you treat a failed call as data: an API error is a 400 with a machine-readable code, so a pipeline step can tell a missing component from an unreachable program. Know that a component is only present if something registered it.
Own the decision of how much of a run is expressed as direct calls at all. Composing paths by hand spreads knowledge of the surface across every script, and the surface is contributed by whichever add-ons happen to be installed on that runner.
## The whole call lives in the path ZAP's control API is ordinary HTTP, and the call you want is spelled out in the URL path rather than in a request document. The path is read **positionally**, not by keyword. The shape is `/<format>/<component>/<reqtype>/<name>/` so `/JSON/core/view/version/` asks the `core` component for the `version` **view** and asks for the answer as JSON. Anything the call needs beyond that travels as ordinary request parameters — a query string on a `GET`, or a form-encoded body on a `POST`. **The format is chosen first, before the program even knows which component you want.** That ordering surprises people who expect a content-negotiation header to decide it, and it is why you cannot ask for a different representation of a call by changing an `Accept` header — you change the first path segment instead. ## What each segment is | segment | what it names | how it is matched | |---|---|---| | `<format>` | the response representation: `JSON`, `JSONP`, `XML`, `HTML`, `UI`, `OTHER` | upper-cased first, so the case you type does not matter | | `<component>` | the prefix a registered implementor claims — `core`, `ascan`, `context`, and one per add-on that exposes an API | exact string match against the registered prefixes | | `<reqtype>` | `view`, `action`, `other` or `pconn` | exact, and the enum constants are lower case | | `<name>` | the individual call inside that component | exact; a trailing query string is trimmed off first | The asymmetry in that right-hand column is the one that bites in a pipeline. The format segment is upper-cased before it is resolved, so `/json/...` and `/JSON/...` are the same request. The request type is not: `/JSON/core/View/version/` is a `bad_type` error, because `View` is not one of the enum constants. `/JSON/Core/view/version/` fails differently again, with `no_implementor`, because the component lookup is an exact map read. ## The four request types, and why the split exists - **`view`** — a read. It returns a structured answer that the API itself serialises into the format you asked for. - **`action`** — a change. Starting a scan, adding a context, loading a session. Same serialisation, different side effects, and a stricter key rule. - **`other`** — the implementor builds the entire HTTP response itself, so this is where raw, non-structured bytes come out: a rendered report, a certificate, a proxy auto-config file. The format segment and this request type are tied together: asking for format `OTHER` on a `view` or an `action` is rejected outright, and asking for any *other* format on an `other` endpoint causes the response the implementor built to be replaced by an empty one. That is why the generated clients build these calls from a separate `/OTHER/` base rather than the `/JSON/` one. - **`pconn`** — a persistent connection. The implementor is handed the raw input and output streams and keeps the socket open, which is how a streaming endpoint delivers events as they happen rather than as one reply. So the split is not cosmetic and it is not about the HTTP method: it is about **who builds the response and how long the connection lives**. Two of the four types produce a document the API formats for you; one produces bytes the component formats; one produces a stream. ## What this means for a pipeline step A step that drives the program over this surface — polling a scan's progress, pulling alerts, kicking off a run — is composing these paths by hand or through a generated client. Three consequences are worth carrying: 1. **A component only answers if something registered it.** Components are not a fixed catalogue; each one is contributed by whatever is installed. Ask for a component whose add-on is absent and you get `no_implementor` — a well-formed error about registration, not a transport failure and not an HTTP 404 page. A step that treats every non-success as "ZAP is down" will misdiagnose it. 2. **Some core prefixes are deprecated shims.** The capability behind them moved into an add-on while the old prefix stayed registered so that old callers still resolve. Reading the prefix alone tells you the call exists, not where the behaviour lives. 3. **Most errors come back in the format you asked for.** An `ApiException` answers `400 Bad Request` with a small object carrying a `code` (the exception type, lower-cased — `bad_type`, `no_implementor`, `illegal_parameter`) and a human `message`; an internal failure answers `500`. So a failed call is usually still a parseable document, and a step that only checks "did I get JSON back" will happily parse an error as if it were a result. The exception is a refused credential, which by default is answered with silence rather than with a document. ## Reaching the surface at all While traffic is being proxied through the program, the API answers on the reserved host `http://zap/` — that is why the generated clients build every URL from a base of `http://zap/JSON/` and send it through the proxy. A request addressed directly to the listener is treated as an API request too. Either way the path is the same; only the host in front of it changes.
- Why is `/JSON/core/View/version/` rejected when `/json/core/view/version/` is not?The format segment is upper-cased before it is resolved, so its case is irrelevant. The request type is matched against enum constants that are spelled in lower case, with no normalising step, so `View` matches nothing and the call comes back as `bad_type`.
- What is the difference between an `other` endpoint and a `view` that returns a big string?A `view` returns a structured result the API serialises into the format you asked for. An `other` endpoint is handed the message and writes the whole response itself — its own content type and raw bytes. The two are tied to the format segment: call an `other` endpoint under `/JSON/` and the response it built is replaced by an empty one, so these calls go under `/OTHER/`.
- A call returns `no_implementor`. What does that tell you?That no registered component claims that prefix in this install — usually because the add-on contributing it is not present. It is a well-formed API error with an HTTP 400, not a transport failure, so a step that reads it as "the program is unreachable" is misdiagnosing a missing add-on.
saying these in an interview costs you the question
- Says the component comes first and the format last
- Names only view and action as the request types
- Assumes the whole path is matched case-insensitively
- Thinks an Accept header selects the response format
- Reads no_implementor as the program being unreachable