What the JetEngine REST API actually reaches

Posted by:

|

On:

|

For months our own field guide carried a sentence saying JetEngine’s MCP endpoint was gated behind an approval step we had not been granted, and should not be architected around. Nobody argued with it. It was written once, and every plan that touched a Crocoblock site after that quietly routed around the JetEngine REST API on the strength of that one line. On 17 August someone sent a request at it anyway. It answered 200.

The note was not a lie. It was a measurement taken once, against one of two doors, then promoted to a property of the building.

What the note actually measured

JetEngine exposes the same tool surface twice. One route looks documented and is the one an agent finds first; the other is a plain JSON-RPC transport one path segment away. Same tools, same credentials. The first returns 403 with an invalid_nonce body, and a WordPress nonce is carried only by a logged-in browser session, so an outside caller can never produce one. The second accepts HTTP Basic auth alone and does the work.

Whoever wrote our note hit the first door and generalised from a failure that named an approval-shaped obstacle. The message was honest, but it described that route’s policy, not the capability’s availability; nothing in the response says which of the two it means. An auth failure naming a nonce, a session or an approval is a statement about one path, not about the capability behind it. When a plugin puts two surfaces on the same tools, the locked one usually has the friendlier documentation.

What the JetEngine REST API reaches, and what it does not

With the transport route answering, most of the data layer is legible from outside with no browser. The configuration comes back in one read: post types, taxonomies, custom content types with their field names, meta boxes, queries, relations. Structures can be created too. On our install that read was worth more than any create call: it showed a complete, empty content type already sitting under the name we were about to build from scratch.

The limits are what change how you plan, and knowing them beforehand is most of the value. The tool set is create-only: no edit tool, no way to change a structure that already exists. Anything wrong at creation time gets fixed by a human in the admin interface, or not at all.

The sharper one: rows cannot be written into a custom content type until that type’s create-item REST endpoint is switched on, and the switch exists only in the interface. Until it is flipped the row-write path is not refusing you — it is not registered, and an unregistered route cannot be reached by any verb, header or credential.

One failure mode defeats the obvious check. A create call against a slug already in use returns HTTP 200, with a success flag set to false and the explanation in the payload: the status reports transport, the verdict is in the body. And before enabling the write endpoint at all, JetEngine below 3.8.6.2 carries CVE-2026-4352, which reaches that same surface. Opening the route is the last step, not the first.

CPT or CCT is a search decision, not a volume one

The choice genuinely expensive to reverse is whether content becomes a Custom Post Type or a Custom Content Type. The tempting reasoning is arithmetic: thousands of rows, so take the type with the dedicated table, because it scales. That reasoning has cost teams months. A Custom Content Type has no native taxonomies and cannot produce archive URLs. Nothing in one can rank, because there is no indexable page for it to rank as. Content that must be found in search needs a post type with real taxonomies, whatever the row count. Reserve the other for high-volume stores your pipeline reads and no crawler sees. Row count is the wrong axis, and it is the one the storage comparison invites you to use.

Why an unverified claim gets more expensive with age

The bug was never in the JetEngine REST API. It was that a claim entered our canon with the same weight as a tested one, and then earned interest.

An untested note has a property that makes it uniquely durable: it saves every reader the cost of trying. That is what documentation is for, and why a wrong entry is worse than none. Everyone who would have probed the endpoint spent nothing instead, and each reading left the note more authoritative, because it had now been read and not contradicted. Citation is not verification, but from outside they look identical.

So the discipline is not to write more carefully. It is to record, beside each claim, what was executed to establish it and when, and to treat any claim without that stamp as an open question, whoever signed it. Documentation is a claim until someone runs it. Ours cost months of routing around a working route, and what fixed it was one person ignoring the note.

The runnable procedure, with its guards and the checkpoint that lets a third party re-derive these limitations, is in the member library.

How we know

Grounded in: our own live install, executed 2026-08-17, correcting the note in our earlier field guide that recorded the JetEngine MCP endpoint as a dead end. Verified: the tool route returned 403 invalid_nonce while the JSON-RPC transport returned 200 for the identical tool and credentials; the configuration read returned two custom content types (13 and 8 fields) and one custom post type (9 fields, two taxonomies), all empty; a create call for an existing slug returned HTTP 200 with success false; the row-write route returned rest_no_route for both content types, establishing the setting as off site-wide rather than per type. The runnable procedure lives in the member library.

Leave a Reply

Your email address will not be published. Required fields are marked *