Skip to content

What the JetEngine REST API actually reaches

JetEngine's REST API exposes two routes with different authentication behavior. Learn what the live endpoint tests proved, and where reads and writes stop.

Published
Updated
AI-generated, checked by independent automated gates, no human editorial review.
How this guide was made

AI-generated. Written by an automated system, checked by independent automated gates, and published without human editorial review. How we label and verify.

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

What the WordPress, Crocoblock and MCP documentation says

Start with authentication, because the 403 in this story is a WordPress rule before it is a JetEngine one. The REST API handbook describes cookie authentication for code running inside WordPress, and it is blunt about what happens without the nonce: If no nonce is provided the API will set the current user to 0, which turns the request into an unauthenticated one even for a logged-in user. A nonce belongs to a browser session. An outside caller has no way to mint one.

External tools are meant to use a different credential. WordPress documents that Application Passwords are typically used via HTTP Basic Authentication, and that they cannot be used to log into wp-admin via wp-login.php. The same page recommends that you Create one per integration/app and revoke any credential that is no longer needed.

The handbook’s vocabulary also explains rest_no_route. A route is a URI which can be mapped to different HTTP methods, and the mapping of one method to a route is an endpoint. If nothing registered the route, there is nothing to map a verb to.

Crocoblock’s own documentation confirms that the row-write route for a Custom Content Type is opt-in. Its tutorial on adding items remotely walks through a toggle named Register create item REST API Endpoint. On storage, the overview states that when you create a Custom Content Type you create a new SQL table in your website database. Crocoblock also documents a “Has Single Page” option where every custom content item will have a corresponding post linked to it. Read that carefully: the public page is a post, which brings you back to the post type decision.

The MCP side is plain JSON-RPC. The specification says MCP uses JSON-RPC to encode messages, and that for HTTP transports servers MUST validate the Origin header. It also splits failures in two. Protocol problems come back as JSON-RPC errors, while tool execution errors are Reported in tool results with an isError flag. A failed tool call can arrive inside a successful response.

How this lines up with what we measured

Each finding in this article has a documented cause. The nonce route returned 403 because WordPress treats a request without a valid nonce as anonymous. The transport route answered because Basic auth with an application password is the path WordPress intends for outside tools. The rest_no_route result for row writes matches a route that was never registered, since the create-item toggle was off. And the create call that returned HTTP 200 with a success flag of false is the same pattern MCP describes for tool results: the transport worked, the operation did not.

None of this was hidden. It was spread across three sets of docs, and our note collapsed it into one sentence about approval.

A checklist before you plan around a JetEngine endpoint

  1. Name the route you tested, not just the plugin. Write down the full path and the auth method used.
  2. For outside callers, use an application password over HTTPS. One per integration.
  3. Treat a nonce error as a statement about cookie auth on that route, nothing more.
  4. Read the response body on every create call. Check the success flag or isError, not the status code.
  5. Run a configuration read first and look for existing types before creating new ones.
  6. Confirm the create-item toggle is on before you plan around a row-write route.
  7. Decide post type or content type on whether the content needs to be found in search.
  8. Stamp each note with the request you ran and the date.

More questions

Why does the nonce route reject a valid application password?

Because it expects cookie authentication. Per the WordPress handbook, a missing nonce sets the current user to 0, so the request is treated as unauthenticated whatever else it carries. Application passwords are meant for a route that accepts Basic auth.

Can a Custom Content Type have public pages at all?

Crocoblock documents a Has Single Page option that links each item to a post. That gives you a page, but the page lives in a post type. If search visibility is the goal, the post type is still where the decision lands.

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.

Related guides

Skill Spotlights · Published

Agent Skills: The Four Bytes Four Gates Missed

Four inspection gates checked 22 agent skills but missed four incorrect bytes. This case shows why teams need different verification methods, not simply more checks of the same kind.

Skill Spotlights · Published

The Slide Deck Check That Read Four-Pixel Text

A slide deck passed its checks despite four-pixel text. Learn to measure rendered legibility at delivery resolution and verify citations against their exact source spans.

Skill Spotlights · Published

Design Tokens Are a Count, Not a Convention

Design tokens need measurable adoption, not just a shared file. Learn how to audit rendered components across light and dark themes and identify styling inconsistencies.