Skip to main content
Plexara
Product10 min read

701 - An automation that answers a request

An endpoint is a lookup or feed another system calls: an automation with a handle(req) function, bound to an address of its own, that answers each request with JSON computed from platform data. What the handler is handed and what it may return, who binds it (an administrator), the limits a request runs under, what a caller is told when something goes wrong, and how a handler is drafted and tested like any other script. Grounded in the store finder on the demo tenant, which answers every active store in a state.

What you will take away from this lesson

An automation runs on demand, on a schedule, once per event, or once per request. The 600 series covered the first three. This series covers the fourth: another system calls an address, and the automation answers it. A store finder on a website, a partner’s replenishment system checking stock, a dashboard in another tool pulling a feed. Each is an endpoint.

This lesson builds the simplest one on the demo tenant, a public store finder, and uses it to show the parts every endpoint shares: the handler, the binding, the limits, and the answers a caller can get.

Learning Objectives

  1. 01Say what an endpoint is, and what it is not: a lookup or feed another system calls, never a web application.
  2. 02Read the request a handler is handed and write the answer it returns.
  3. 03Name who binds an automation to an endpoint and the settings a binding holds.
  4. 04State the limits one request runs under and what a caller is told when it fails.
  5. 05Draft and test a handler the way any automation is drafted and tested.

Where this lesson sits

The 700 series starts from the automations of the 600 series. An endpoint is an automation that runs once per request, and a form is an endpoint people fill in.

700 Series: Endpoints and Forms

Open index

The 700 series builds on the automations of the 600 series: an endpoint is an automation that answers a request, and a form is an endpoint that people fill in.

What an endpoint is

An endpoint answers a request from another system with data the platform holds, under the same governance as every other automation.

What an endpoint is

An automation

An endpoint is a managed script like any in the 600 series: written by the agent, saved with tests, versioned, and run under the access its author held at the save. What makes it an endpoint is one function, handle(req), and a binding to an address.

An address

/endpoints/<name>

Each binding has a name unique across the deployment. A request to that address runs the handler on the server that received it and answers with what the handler returns.

A lookup or feed

The answer is data: JSON computed from the warehouse, the catalog, an API connection, or anything else the automation may reach. Every answer is served as an opaque document that runs no script, and is not cached unless the handler says so.

Not web hosting

An endpoint does not serve a website or an application. It answers requests with data, one at a time, inside fixed limits. A page people fill in is a form, the subject of 703.

A request writes no run to the automation’s run history. It writes one audit row of its own, and every platform call the handler makes is audited under the automation’s name, as a scheduled run’s calls are. Lesson 702 reads those rows.

The request a handler is handed

The platform hands the handler one dictionary per request. The caller’s credentials are never in it; the platform has already decided who the caller is.

What handle(req) is handed

method

The HTTP method: GET, POST, PUT, PATCH, DELETE, or HEAD.

path

The path the caller sent.

params

Values from the binding’s path template. A template of /{sku} hands the segment over as params["sku"].

query

The first value of each query parameter, such as query["state"].

headers

The request headers with names in lower case. The caller’s credentials (Authorization, Cookie, X-API-Key) are left out.

body, json, form

The body as bytes, parsed as JSON when it says it is JSON, and as fields when it is a URL-encoded form. A body that claims to be JSON and is not is refused before the handler runs.

caller

Who the platform found the caller to be, on an endpoint that requires sign-in or a key: their id, email, and whether they used a session or an API key. It never comes from the request body. Lesson 702 covers the access modes.

The handler returns a status (200 unless it says otherwise), optional headers, and either json or a body. It may not set cookies or the headers that control framing, scripts, or cross-origin access; the platform sets those on every answer.

The store finder

Asked for a store finder the ACME website could call, the agent wrote a handler that answers every active store in one state.

acme-store-finder, the handler

def handle(req):
    """Lists the active ACME stores in one state, for the store finder on acme.example.com."""
    state = req["query"].get("state", "").upper()
    if state not in STATES:
        return {"status": 400, "json": {"error": "state must be a two-letter US state code"}}
    rows = platform.query(
        "SELECT s.store_id, s.store_name, s.address, s.city, s.state, s.zip_code, s.phone, " +
        "r.region_name AS region FROM warehouse.public.stores s " +
        "JOIN warehouse.public.regions r ON r.region_id = s.region_id " +
        "WHERE s.is_active AND s.state = :state ORDER BY s.city, s.store_id",
        params = {"state": state},
        connection = "acme",
    )
    return {
        "headers": {"Cache-Control": "public, max-age=300"},
        "json": {"state": state, "count": len(rows["rows"]), "stores": rows["rows"]},
    }

The automation the agent saved on the demo tenant, less its list of state codes and its tests. The state is checked against a fixed list before it reaches SQL, the query binds it as a parameter, and the answer allows a five-minute cache because the store list changes rarely. Nothing else about the warehouse is reachable through the address.

Putting it at an address

A saved automation answers nothing until it is bound. The binding names the address, the methods, who may call, and the limits.

Binding the store finder

What the agent calls. This is the exchange the agent has with Plexara on your behalf, shown for the technical reader. You ask in plain language; you never type any of it.

→ manage_script
  {
    "command": "endpoint_set",
    "name": "acme-store-finder",
    "endpoint": "store-finder",
    "methods": ["GET"],
    "auth_mode": "bot_check",
    "bot_check": "default",
    "allowed_origins": ["https://www.example.com"],
    "rate_limit": 300,
    "timeout_seconds": 10
  }

← {
    "endpoint": "store-finder",
    "enabled": true,
    "url": "https://mcp-demo.plexara.io/endpoints/store-finder",
    "max_body_bytes": 1048576,
    "max_memory_bytes": 67108864,
    "caller_rate_limit": 120,
    "message": "acme-store-finder now answers GET at
                https://mcp-demo.plexara.io/endpoints/store-finder."
  }

Binding is an administrator’s action. The automation’s owner cannot bind it, so an address that answers the outside world exists because an administrator on your team decided it should. An administrator can do the same on the automation’s page in the portal, in its Endpoint section, and turn the endpoint off there without touching the automation; a turned-off endpoint answers 404.

A binding is refused for a script with no handle, and a later save that removes it is refused too, naming the endpoint.

An automation's page in the portal: a Details card with its owner, schedule, events and status, then collapsible Schedule, Events and Endpoint sections, the Endpoint section reading On at /endpoints/supplier-onboarding, and a Submissions section below.
An automation's page names the endpoint it answers at, beside its schedule and the webhook source it runs for.

What a binding holds

Every setting has a standard value except the name and the access mode, which an administrator always chooses.

What a binding holds

endpoint

The name in the address. Lowercase letters, digits, hyphens, and underscores, unique across the deployment.

methods, path

The methods answered (GET unless set) and an optional template under the name, such as /{sku}.

auth_mode

Who may call: authenticated, public, or bot_check. Required, with no default. Lesson 702.

timeout_seconds

10, at most 60

How long one request may run before the caller is answered 504.

max_body_bytes

1 MiB, at most 10 MiB

The largest body accepted. A larger one is answered 413 and the handler never runs.

rate_limit

600 a minute

Requests a minute the endpoint takes on each server. Past it, a caller is answered 429 with a time to retry.

allowed_origins

Websites whose browsers may call the endpoint directly from a page. Empty answers no cross-origin request.

One request

The store finder page on the website sends the state a visitor picked and renders the stores it gets back.

One request to the store finder

What the calling system sends. This is the HTTP exchange the store finder page on the ACME website has with the endpoint, shown for the technical reader. The calling system sends it on its own; nobody types it.

GET /endpoints/store-finder?state=il
X-Bot-Check: <the answer to the store finder's challenge>

200 OK
Cache-Control: public, max-age=300
Content-Security-Policy: default-src 'none'; sandbox

{
  "state": "IL",
  "count": 12,
  "stores": [
    { "store_id": 103, "store_name": "ACME Store #103", "address": "1202 Park Dr",
      "city": "Arlington", "state": "IL", "zip_code": "96952",
      "phone": "(926) 696-6809", "region": "Midwest" },
    { "store_id": 96, "store_name": "ACME Store #96", "address": "5141 Main Rd",
      "city": "Ashland", "state": "IL", "zip_code": "45629",
      "phone": "(965) 820-6941", "region": "Midwest" },
    ... ten more
  ]
}

The page fetched a proof-of-work challenge, solved it in a fraction of a second, and sent the answer with the request. Lesson 704 covers bot checks. The handler answered in the time it took to run one query.

What a caller is told

Some answers come from the handler and the rest from the platform, before or after the handler runs.

What a caller is told

400

from the handler

Whatever the handler decides. The store finder answers 400 with a message for an unknown state.

404

No enabled endpoint has the name, or the path does not match the template.

405

The method is not one the endpoint answers; the answer lists the ones it does.

413

The body is larger than the binding allows. The handler does not run.

429

Past the endpoint’s rate, or the caller’s own rate on an authenticated endpoint, with a time to retry.

500

The handler failed, or returned something that is not an answer.

503

The automation is disabled or superseded, the handler held too much memory, or the server is already running its share of handlers.

504

The handler ran past its timeout.

A caller learns which of these it got and never the automation’s error. The error is kept for seven days with the request’s status and duration, listed on the automation’s page, where the owner reads it.

Limits

Each request runs inside fixed limits, so one slow or greedy caller cannot hold the platform up for the rest.

The limits one request runs under

default time per request, at most 60
10 s
memory one request may hold
64 MiB
default body, at most 10 MiB
1 MiB
handlers running at once on each server
32

Rate limits count on each server, and no limit depends on the caller’s network address. A handler cannot write an output or refresh a dashboard: a request answers with what handle returns, and work that should leave something behind belongs to a run, started by a schedule or by an event.

Drafting and testing a handler

A handler is written the way every automation is written: drafted for real, tested against a recording, and saved only when the tests pass.

Drafting and testing a handler

  1. 1

    Draft with a request built by hand

    A draft runs main(), so the agent writes a main() that calls handle with the request a caller would send. The draft runs for real and records every platform call and its answer.

  2. 2

    Test against the recording

    A test replays that recording and asserts on the answer: the store finder’s tests check that Illinois returns 12 stores in the Midwest and that ZZ is answered 400.

  3. 3

    Save, and the tests run

    A save runs the tests as it does for any automation and is refused while one fails or a branch is never reached.

  4. 4

    Every request runs the newest version

    The first request after a save runs the new version on every server. There is no separate deploy step.

The loop is the one lesson 602 taught. The agent writes the handler, runs the draft, writes the tests, and saves; an administrator binds it once it is right.

Key terms

Four terms cover what an endpoint is and how it is put at an address.

Key Terms

Endpoint
An automation bound to an address of its own that answers each request with data. A lookup or feed another system calls.
Handler
The handle(req) function the platform calls with each request. Its return value is the answer.
Binding
The settings that put an automation at an address: name, methods, path, access mode, limits, and allowed origins. Set by an administrator.
Access mode
Who may call an endpoint: authenticated callers, anyone, or anyone who passes a named bot check.