Skip to content

Pipe Reference

Civi::pipe was introduced in CiviCRM v5.47.

The Civi::pipe transport provides a request-response mechanism for executing multiple tasks within a single CiviCRM process. It uses a line-oriented message protocol and complies with JSON-RPC v2.0. The transport is compatible with several mechanisms for bootstrapping CiviCRM.

The list of valid method calls is purposefully short. It allows for establishing/testing a session, authenticating, and sending API calls (APIv3 and APIv4).

Example

This example connects to a CiviCRM site running in /var/www/example.com/web and issues two requests.

In bash, open the pipe:

$ cd /var/www/example.com/web
$ cv ev 'Civi::pipe();'

The command responds with a welcome message:

{"Civi::pipe":{"v":"5.47.alpha1","t":"trusted","l":["login"]}}

Within this pipe, we may send requests and receive responses:

// Send request for `echo("hello world")`
{"jsonrpc":"2.0","method":"echo","params":["hello world"],"id":null}
// Receive response "hello world"
{"jsonrpc":"2.0","result":["hello world"],"id":null}

// Send request for `api3("System", "flush")`
{"jsonrpc":"2.0","method":"api3","params":["System","flush",{"check_permissions":0}],"id":null}
// Receive response
{"jsonrpc":"2.0","result":{"is_error":0,"version":3,"count":1,"values":1},"id":null}

Overview

The general flow for a pipe session is:

  1. A client opens a connection to Civi::pipe()
  2. The server responds with a header (UTF-8, one-line, JSON).
  3. The client submits a request (UTF-8, one-line, JSON-RPC).
  4. The server sends a response (UTF-8, one-line, JSON-RPC).
  5. Go back to (3).

Requests are executed synchronously with a single thread of operation (one request then one response). This parallels the PHP-HTTP architecture ordinarily used by CiviCRM (one process handles one request at a time). However, it expands the lifetime of the PHP process to serve multiple requests. This avoids redundant bootstraps. It is suitable for a series of requests with a common context (eg several requests by the same user).

The pipe protocol is specifically focused on two-channel communication (STDIN/STDOUT). If there is a third (STDERR) channel, then the client MAY log or display it for debugging purposes. However, STDERR must be ignored when parsing requests and responses.

Connection

CLI

The function Civi::pipe() begins the server process for evaluating requests. Here are a few examples to invoke Civi::pipe():

## Start with cv
$ cd /var/www/example.com/web
$ cv ev 'Civi::pipe();'
{"Civi::pipe":{"v":"5.47.alpha1","t":"trusted","l":["login"]}}

## Start with drush
$ cd /var/www/example.com/web
$ drush ev 'civicrm_initialize(); Civi::pipe();'
{"Civi::pipe":{"v":"5.47.alpha1","t":"trusted","l":["login"]}}

## Start with wp-cli
$ cd /var/www/example.com/web
$ wp eval 'civicrm_initialize(); Civi::pipe();'
{"Civi::pipe":{"v":"5.47.alpha1","t":"trusted","l":["login"]}}

## Start with SSH + cv
$ ssh webuser@backend.example.com cv ev --cwd=/var/www/example.com/web ev "Civi::pipe();"
{"Civi::pipe":{"v":"5.47.alpha1","t":"trusted","l":["login"]}}

At this point, the connection is established, and you may send requests.

Flags

When connecting, the pipe provides a welcome message with a series of flags.

Advanced clients may request a list of connection flags when calling Civi::pipe(). Connection flags are useful for both reporting about the connection and requesting specific features.

For example, this requests two flags (v, u) and receives a welcome message:

Civi::pipe("vu");
{"Civi::pipe":{"v":"5.47.alpha1","u":"untrusted"}

The v flag reports on the active CiviCRM version. The u flag marks the session as untrusted (which ensures that API calls must enforce permissions).

Valid flags are:

  • v (version): Report the CiviCRM version. Ex: "v":"5.48.0"
  • j (json-rpc): Report supported flavors of JSON-RPC. Ex: "j":["jsonrpc-2.0"]
  • l (login): Report whether user logins are supported. Values may be"l":["login"] (if the server supports AuthX) or "l":["nologin"] (if there are no login mechanisms).
  • t (trusted): Mark session as trusted. Logins do not require credentials. API calls may execute with or without permission-checks.
  • u (untrusted): Mark session as untrusted. Logins require credentials. API calls may only execute with permission-checks.

Unrecognized flags must not cause a failure. They must report as null. In this example, x is an unrecognized flag:

Civi::pipe("uxv");
{"Civi::pipe":{"u":"untrusted","x":null,"v":"5.48.0"}

Line format

Each request and response is a JSON object formatted to fit on a single line. Lines are separated with the conventional newline character (\n).

Payload data MAY include escaped newlines ("\n").

JSON is rendered in condensed / ugly / non-"pretty-printed" format. It MUST NOT include the line-delimiter as whitespace.

For readability, some long examples in the documentation may be displayed with multiple lines. But these lines are not transmitted over the wire.

Each request-line and each response-line is formatted according to JSON-RPC v2.0.

Many PHP deployments include misconfigurations, bugs, or add-ons -- which can cause extra noise to be presented on STDOUT. Clients SHOULD use the session option responsePrefix to detect and discard noise.

Methods

api3

The api3 method is used to invoke APIv3 actions. It receives the standard tuple of entity-action-params.

For example, to send a request for Contact.get with rowCount=4 and check_permissions=false:

> {"jsonrpc":"2.0",
   "method":"api3",
   "params":["Contact","get",{"rowCount":4,"check_permissions":false}],
   "id":null}
< {"jsonrpc":"2.0",
   "result":{"is_error":0,"count":4,values:[...]},
   "id":null}

By defaut, APIv3 errors are converted to JSON-RPC error-format. For some use-cases, this could lose precision or interoperability. You may change the error format with the apiError option.

By default, APIv3 requests received on Civi::pipe() will enforce permission-checks. On trusted connections, you may opt-out with "check_permissions":false or the apiCheckPermissions option.

api4

The api4 method is used to invoke APIv4 actions. It receives the standard tuple of entity-action-params.

> {"jsonrpc":"2.0",
   "method":"api4",
   "params":["Contact","get",{"limit":4,"checkPermissions":false}],
   "id":null}
< {"jsonrpc":"2.0",
   "result":[{"id":1,"contact_type":"Organization",...}],
   "id":null}

By defaut, APIv4 errors are converted to JSON-RPC error-format. For some use-cases, this could lose precision or interoperability. You may change the error format with the apiError option.

By default, APIv4 requests received on Civi::pipe() will enforce permission-checks. On trusted connections, you may opt-out with "checkPermissions":false or the apiCheckPermissions option.

echo

The echo message is used for testing. It simply returns the input.

> {"jsonrpc":"2.0","method":"echo","params":["hello world"],"id":null}
< {"jsonrpc":"2.0","result":["hello world"],"id":null}

login

Requirements: Login requires enabling the AuthX extension.

Set the active user/contact.

> {"jsonrpc":"2.0","method":"login","params":{"contactId":202},"id":null}
< {"jsonrpc":"2.0","result":{"contactId":202,"userId":1},"id":null}

The login principal may be specified with any ONE of the following:

  • cred (string; an AuthX credential such as Bearer s3cr3tk3y)
  • contactId (int; requires trusted mode)
  • userId (int; requires trusted mode)
  • user (string; requires trusted mode)

options

The options method manages connectivity options. By default, it will return a list of all known options:

> {"jsonrpc":"2.0",
   "method":"options",
   "id":null}
< {"jsonrpc":"2.0",
   "result":{"responsePrefix":null,"bufferSize":524288},
   "id":null}

Additionally, you may use it to update an option. Any modified options will be returned.

> {"jsonrpc":"2.0",
   "method":"options",
   "params":{"responsePrefix":"\u0001\u0001"},
   "id":null}
< {"jsonrpc":"2.0",
   "result":{"responsePrefix":"\u0001\u0001"},
   "id":null}

The following options are defined:

  • apiCheckPermissions (bool): By default, on all connections, API calls are executed with the checkPermissions/check_permission flag. This default may be switched off (for trusted connections).
  • apiError (string): Specify how CiviCRM APIs should report their errors. Either:
    • array: Errors are reported as part of the API's result-array. Useful for precise+generic handling.
    • exception: Errors are converted to exceptions and then to JSON-RPC errors. Some JSON-RPC clients will convert these to client-side exceptions.
  • bufferSize (int): The maximum length of a line in the control session, measured in bytes. This determines the maximum request size. (The default value is deployment-specific/implementation-specific. The default must be at least 64kb. At time of writing, the default for civicrm-core is 512kb.)
  • responsePrefix (string): Before sending any response (but after evaluating the request), send an extra prefix or delimiter. (Defensively-coded clients may set a prefix and watch for it. If any output comes before the prefix, then the client may infer that the server is misbehaved - eg a debug hack or a bad plugin is creating interference. Disregard output before the prefix.)

Special cases

  • If a request-line is received with an empty-string, it is ignored by the server.