Documentation menu

HTTP API

arclang serve starts a local HTTP server. It compiles source text on request, and serves each model given on the command line as a project of the Systems Modeling API, the resource model the OMG standardized with SysML v2.

arclang serve model.arc --port 5001

The server listens on the loopback interface only. It is a local or trusted-network service, not an internet-facing one: there is no rate limiting.

The examples below run against this model, served on port 5417.

brake.arc
model BrakeAssist {
  version: "1.0.0"

  requirements safety {
    req "REQ-001" "Braking reaction" { description: "Command braking within 100 ms" }
  }

  architecture logical {
    component "Brake controller" {
      id: "LC-BRAKE"
      function "Command braking" { latency: 25 ms }
    }
  }
}

trace "LC-BRAKE" satisfies "REQ-001"

Compile source text

POST /api/compile takes ArcLang source and returns the compiled semantic model, with the stable UUID of each element, or a structured error with its position.

$ curl -sf -X POST localhost:5417/api/compile -H 'content-type: application/json' -d '{"source": "model Demo { requirements safety { req \"R-1\" \"Range\" { description: \"400 km\" } } }"}'
{"model":{"all_elements":{"R-1":{"element_type":"Requirement","id":"R-1","name":"R-1","uuid":"595e834c-a703-57cc-83a3-9753fbaf77a8"}},"capabilities":[],"components":[],"constraints":[],"functional_chains":[],"functions":[],"interfaces":[],"missions":[],"name":"Demo","requirements":[{"category":null,"description":"400 km","id":"R-1","priority":"Medium","safety_level":null}],"traces":[],"types":[]},"success":true,"warnings":[]}
$ curl -s -X POST localhost:5417/api/compile -H 'content-type: application/json' -d '{"source": "model Demo { widget Foo { } }"}'
{"error":"Parser error: Unexpected token in model block: Identifier(widget) at line 1, column 14","success":false}

GET /api/metamodel returns the metamodel as JSON: element kinds, typed attributes, enumerations, units and trace rules.

Projects and commits

Each served model is a project with one branch, main.

$ curl -sf localhost:5417/api/systems-modeling/projects
[{"@id":"1d50b9fa-5b40-57de-bcc5-304d689d9127","@type":"Project","alias":[],"created":"2026-11-07T14:38:35Z","defaultBranch":{"@id":"64142a27-703d-5346-a384-d3e361d5e57d"},"description":null,"name":"BrakeAssist"}]

A commit is a compiled snapshot of the model. Its identifier is content-addressed: reformatting the model does not create a new snapshot.

$ curl -sf localhost:5417/api/systems-modeling/projects/1d50b9fa-5b40-57de-bcc5-304d689d9127/commits
[{"@id":"92683ae3-a4b0-5d01-8a62-ffddae1c14a9","@type":"Commit","alias":[],"created":"2026-11-07T14:38:35Z","description":"Compiled snapshot of 'BrakeAssist': 4 elements, 1 relationships","name":null,"owningProject":{"@id":"1d50b9fa-5b40-57de-bcc5-304d689d9127"},"previousCommit":[]}]

Elements and relationships

Under a commit, the API serves the elements, the relationships between them, and the roots of the model. Every element has a deterministic UUID, an owner, a qualified name and typed attributes; a quantity carries its unit and its SI value.

$ curl -sf localhost:5417/api/systems-modeling/projects/1d50b9fa-5b40-57de-bcc5-304d689d9127/commits/92683ae3-a4b0-5d01-8a62-ffddae1c14a9/elements/29bb411c-8fe8-5afc-b814-d620bc04cc9e | python3 -m json.tool
{
    "@id": "29bb411c-8fe8-5afc-b814-d620bc04cc9e",
    "@type": "LogicalFunction",
    "attributes": {
        "latency": {
            "@type": "Quantity",
            "canonicalUnit": "s",
            "canonicalValue": 0.025,
            "dimension": "time",
            "unit": "ms",
            "value": 25.0
        }
    },
    "declaredName": "Command braking",
    "declaredShortName": "Command braking",
    "elementId": "29bb411c-8fe8-5afc-b814-d620bc04cc9e",
    "name": "Command braking",
    "ownedElement": [],
    "ownedRelationship": [],
    "owner": {
        "@id": "0aac9533-80c0-5207-8d22-5fd4f51e826f"
    },
    "qualifiedName": "BrakeAssist::Brake controller::Command braking",
    "shortName": "Command braking"
}

Identifiers are deterministic: the UUID of an element is derived from its id, so the address above is the same on every machine and after every restart.

Resource, under /projects/{id}/commits/{id} Content
/elements Every element and relationship (traces, exchanges, typing). Cursor pagination with page[size], page[after], page[before] and a Link header
/elements/{id} One element
/elements/{id}/relationships?direction=in|out|both The relationships of one element
/roots The top-level elements
/changes Elements added, modified or deleted since the previous commit (useful with --history)

Ad-hoc queries are sent to POST /projects/{id}/query-results, with primitive and composite constraints as the standard defines them.

A relationship whose end does not resolve is listed in the commit, never dropped.

Git history as commits

With --history, each git commit that touched the model file is a commit of the API, with imports resolved at that revision. The uncommitted working tree is the head when it differs. A revision that no longer compiles is served as an empty commit that carries the compiler's error.

arclang serve model.arc --history --history-depth 50

Conformance

Projects, branches, commits and errors follow the schemas of the OMG Systems Modeling API. ArcLang's own fields (the compiler error of a revision, the files of a commit) are added only when asked, with ?extensions=true. Not served: creating or deleting projects, branches and tags, saved queries, /diff and /merge. The SysML v2 vocabulary below names the metaclass of each element and the properties ArcLang holds, not every property of the metaclass.

Two vocabularies

The same commits are served under two roots:

  • /api/systems-modeling: @type is a kind of the ArcLang metamodel.
  • /api/sysml-v2: @type is a KerML or SysML v2 metaclass. See SysML v2.
$ curl -sf "localhost:5417/api/sysml-v2/projects/1d50b9fa-5b40-57de-bcc5-304d689d9127/commits/92683ae3-a4b0-5d01-8a62-ffddae1c14a9/elements?page%5Bsize%5D=200" | tr '{' '\n' | grep -o '"@type":"[A-Za-z]*"' | sort | uniq -c | sort -rn | head -8
  43 "@type":"OwningMembership"
  31 "@type":"MetadataDefinition"
   8 "@type":"AttributeUsage"
   6 "@type":"FeatureTyping"
   5 "@type":"FeatureMembership"
   4 "@type":"Package"
   4 "@type":"FeatureValue"
   3 "@type":"ReferenceUsage"

Authentication

Without options, the API is open to the local machine. Two options protect it:

  • --token-file <file>, or the ARCLANG_API_TOKEN environment variable: one shared token. Every request under /api must send Authorization: Bearer <token>.
  • --users-file <file>: one user per line, name role token, the role being read or write. The token is given in clear or as sha256:<hex digest>, so the file need not hold a secret.

Tokens are at least 24 characters long. Only their SHA-256 is kept in memory. A reader who writes gets a 403.

Writes as git commits

Writes are opt-in and need a token:

arclang serve model.arc --history --allow-write --token-file api.token

POST /projects/{id}/commits takes a description, the commit it is based on and a list of changes. A change can set or remove attributes of an element, rename it, create an element (actor, requirement, system function, logical component, logical function, physical node), delete one with what it contains, and create or delete a trace.

The request is applied to the model file as lossless edits: comments and layout are kept. It is all or nothing, and becomes one git commit of that file with the request's description. Nothing is written unless the edited model compiles and holds exactly what was asked. A file with uncommitted changes, or a request based on a commit that is no longer the head, is refused with a 409.

Not supported: other kinds of elements and relationships, elements declared in imported files, projects and branches. Rights are per user, not per project.

For AI agents

The repository includes an MCP server (mcp-server/) that exposes compile, validate, trace and export to language-model agents, aligned with the command line.

Every ArcLang sample on this page is compiled, and every command is run, with the released compiler when the site is built.