REST API

Start the REST server with:

graphwalker online -s RESTFUL -p 8080 -m model.json "random(edge_coverage(100))"

All endpoints are under the /graphwalker path prefix.

Legacy execution response format

The execution endpoints documented in the next section preserve their existing wire format. Successful responses include "result": "ok". Errors include "result": "nok" with an "error" message.

The draft-authoring API uses conventional HTTP status codes and typed JSON responses instead. It never adds a result wrapper.


POST /graphwalker/load

Load a model and initialize the execution engine.

Request body: JSON model definition (the full model file content).

Response:

{
  "result": "ok",
  "seed": 7298345612
}

The returned seed can be used later to reproduce the same traversal.

Error example:

{
  "result": "nok",
  "error": "Model has no generator specified"
}

GET /graphwalker/hasNext

Check whether more steps are available.

Response:

{
  "result": "ok",
  "hasNext": "true"
}

Returns "false" when the stop condition is fulfilled.

Error (no model loaded):

{
  "result": "nok",
  "error": "No model(s) are loaded."
}

GET /graphwalker/getNext

Advance to the next element and return it.

Response:

{
  "result": "ok",
  "currentElementName": "e_Login",
  "currentElementID": "e1",
  "modelId": "853429e2-0528-48b9-97b3-7725eafbb8b5"
}
Field Description
currentElementName Name of the current element (vertex or edge)
currentElementID ID of the current element
modelId ID of the model containing the element

GET /graphwalker/getData

Get the current execution data (all variables).

Response:

{
  "result": "ok",
  "data": "loggedIn=true; itemCount=3"
}

The data field is a string representation of all variables in the execution context.


PUT /graphwalker/setData/{script}

Execute a script to modify execution data. The script is passed as a URL path parameter.

Example request:

PUT /graphwalker/setData/loggedIn%20%3D%20true%3B

(URL-decoded: loggedIn = true;)

Response:

{
  "result": "ok"
}

PUT /graphwalker/restart

Reset execution to the initial state. The model remains loaded but all visit counts, variables, and state are cleared.

Response:

{
  "result": "ok"
}

GET /graphwalker/getStatistics

Get coverage statistics for the current execution.

Response:

{
  "result": "ok",
  "totalNumberOfVertices": 5,
  "totalNumberOfEdges": 8,
  "totalNumberOfVisitedVertices": 3,
  "totalNumberOfVisitedEdges": 6,
  "totalNumberOfUnvisitedVertices": 2,
  "totalNumberOfUnvisitedEdges": 2,
  "vertexCoverage": 60,
  "edgeCoverage": 75
}
Field Description
totalNumberOfVertices Total vertices in all models
totalNumberOfEdges Total edges in all models
totalNumberOfVisitedVertices Vertices visited at least once
totalNumberOfVisitedEdges Edges visited at least once
totalNumberOfUnvisitedVertices Vertices not yet visited
totalNumberOfUnvisitedEdges Edges not yet visited
vertexCoverage Percentage of vertices visited (0–100)
edgeCoverage Percentage of edges visited (0–100)

Model draft authoring

Model authoring is an independent, resource-oriented API under /graphwalker/drafts. Drafts are process-local and ephemeral: export a completed model before the server stops. Starting or restarting the REST server discards every draft.

The server can be started without preloading a model when only authoring is needed:

graphwalker online -s RESTFUL -p 8080

Every successful mutation returns the new numeric revision. Mutation bodies accept an optional expected_revision; if it does not equal the current revision, the server returns 409 Conflict without changing the draft. Supplying revisions is recommended whenever multiple requests or clients could edit the same draft.

JSON request bodies are limited to 1 MiB and must use Content-Type: application/json or a compatible application/*+json media type. Exported models retain the canonical GraphWalker field names described in the JSON format, while authoring request and response envelope fields use snake_case.

Authoring routes

Method Route Success Purpose
POST /graphwalker/drafts 201 Created Create an empty single-model draft
GET /graphwalker/drafts/{draft_id} 200 OK Export canonical GraphWalker JSON and its revision
PATCH /graphwalker/drafts/{draft_id} 200 OK Patch model metadata
DELETE /graphwalker/drafts/{draft_id} 200 OK Discard the draft
POST /graphwalker/drafts/{draft_id}/vertices 201 Created Add a vertex
PATCH /graphwalker/drafts/{draft_id}/vertices/{vertex_id} 200 OK Patch a vertex
POST /graphwalker/drafts/{draft_id}/edges 201 Created Add an edge
PATCH /graphwalker/drafts/{draft_id}/edges/{edge_id} 200 OK Patch an edge
DELETE /graphwalker/drafts/{draft_id}/elements/{element_id} 200 OK Remove a vertex or edge
GET /graphwalker/drafts/{draft_id}/validation 200 OK Validate the current draft

Create a draft

POST /graphwalker/drafts

All fields are optional. Omitted list and object fields default to empty values.

{
  "model_id": "checkout-model",
  "name": "Checkout",
  "generator": "random(edge_coverage(100))",
  "actions": ["global.started = true"],
  "requirements": ["REQ-1"],
  "properties": { "owner": "payments" }
}

Response (201 Created):

{
  "draft_id": "draft_550e8400-e29b-41d4-a716-446655440000",
  "model_id": "checkout-model",
  "revision": 0
}

When model_id is omitted, GraphWalker generates it. The draft_id identifies mutable server state and is deliberately different from the GraphWalker model ID.

Add vertices and edges

POST /graphwalker/drafts/{draft_id}/vertices

{
  "id": "v_cart",
  "name": "v_Cart",
  "shared_state": null,
  "actions": [],
  "requirements": ["REQ-CART"],
  "properties": {},
  "expected_revision": 0
}

Response (201 Created):

{
  "vertex": {
    "id": "v_cart",
    "name": "v_Cart",
    "shared_state": null,
    "actions": [],
    "requirements": ["REQ-CART"],
    "properties": {}
  },
  "revision": 1
}

POST /graphwalker/drafts/{draft_id}/edges

{
  "id": "e_start",
  "name": "e_Start",
  "source_vertex_id": null,
  "target_vertex_id": "v_cart",
  "guard": null,
  "actions": [],
  "requirements": [],
  "properties": {},
  "weight": 1.0,
  "dependency": 0,
  "expected_revision": 1
}

target_vertex_id is required and must identify an existing vertex. Omit source_vertex_id or set it to null for a start edge. Element IDs must be unique across both vertices and edges. Weight must be between 0.0 and 1.0; dependency must be between 0 and 100.

Patch a model, vertex, or edge

Use PATCH with only the fields that should change. An omitted field is retained. An explicit null clears an optional field or resets a list/object field to its empty value.

Set the start element:

PATCH /graphwalker/drafts/{draft_id}
Content-Type: application/json
{
  "start_element_id": "e_start",
  "expected_revision": 2
}

Model patch fields are name, generator, start_element_id, actions, requirements, properties, and predefined_path_edge_ids.

Vertex patch fields are name, shared_state, actions, requirements, and properties. Edge patch fields are name, source_vertex_id, target_vertex_id, guard, actions, requirements, properties, weight, and dependency. target_vertex_id cannot be cleared.

Export and validate

GET /graphwalker/drafts/{draft_id} returns a JSON object rather than a JSON-encoded string:

{
  "model": {
    "models": [
      {
        "id": "checkout-model",
        "generator": "random(edge_coverage(100))",
        "vertices": [],
        "edges": []
      }
    ]
  },
  "revision": 3
}

GET /graphwalker/drafts/{draft_id}/validation returns ordered validation messages:

{
  "valid": true,
  "issues": [],
  "revision": 3
}

Validation does not mutate the draft. A missing or invalid generator is reported as an issue.

Remove elements and discard drafts

DELETE /graphwalker/drafts/{draft_id}/elements/{element_id} accepts query parameters:

Parameter Default Description
cascade false Also remove edges connected to a deleted vertex
cleanup_references false Remove references from the start element and predefined path
expected_revision omitted Require the current draft revision

Example response:

{
  "removed_ids": ["e_checkout", "v_checkout"],
  "revision": 8
}

DELETE /graphwalker/drafts/{draft_id} releases the complete draft and returns:

{ "discarded": true }

Later requests for that ID return 404 Not Found.

Authoring errors

Authoring failures always return a JSON body:

{
  "code": "revision_conflict",
  "message": "Expected revision 3, but the draft is at revision 4"
}
Status Typical codes
400 Bad Request invalid_json, invalid_query
404 Not Found draft_not_found
409 Conflict revision_conflict, duplicate_element_id, referenced_element
410 Gone draft_expired
413 Payload Too Large payload_too_large
415 Unsupported Media Type unsupported_media_type
422 Unprocessable Entity invalid_model, unknown_vertex, missing_target_vertex, invalid_weight, invalid_dependency, invalid_element
429 Too Many Requests draft_limit_reached, model_limit_reached
500 Internal Server Error draft_unavailable, internal

Failed mutations are atomic: neither the model nor its revision changes.


Typical usage pattern

# 1. Load a model (or start the server with -m flag to pre-load)
curl -X POST http://localhost:8080/graphwalker/load -d @model.json

# 2. Loop: check and step
while curl -s http://localhost:8080/graphwalker/hasNext | grep -q '"true"'; do
  STEP=$(curl -s http://localhost:8080/graphwalker/getNext)
  echo "$STEP"
  # Execute the test step indicated by currentElementName
done

# 3. Check final coverage
curl -s http://localhost:8080/graphwalker/getStatistics

Seed and determinism

When starting with --seed <value>, the same seed produces identical traversal paths. The seed is also returned by the /load endpoint, so you can capture it and replay later:

# Capture the seed
SEED=$(curl -s -X POST http://localhost:8080/graphwalker/load -d @model.json | jq -r '.seed')
echo "Seed: $SEED"

# Replay with the same seed later
graphwalker online -s RESTFUL --seed $SEED -m model.json "random(edge_coverage(100))"