Skip to content

Protocol

Core request and response structure


A Vend request is a JSON object with the following structure:

{
"protocol": { "name": "vend", "version": "0.1.0" },
"id": "req_abc123",
"call": {
"function": "service.action",
"version": "1",
"arguments": { }
},
"context": { },
"extensions": [ ]
}
FieldTypeRequiredDescription
protocolstringYesProtocol identifier and version. MUST use format: vend/<major>.<minor>
idstringYesUnique request identifier. MUST correlate request to response.
callobjectYesThe function invocation details
contextobjectNoPropagated metadata. See Context.
extensionsarrayNoExtension objects with urn and options. See Extensions.

The call object specifies what function to invoke:

FieldTypeRequiredDescription
functionstringYesFunction identifier MUST use <service>.<action> format
versionstringNoFunction version. Defaults to latest. See Versioning.
argumentsobjectNoFunction arguments. Defaults to empty object {} if omitted.

The id field uniquely identifies a request attempt.

Type: String only. Implementations SHOULD use one of:

  • UUID v4: "550e8400-e29b-41d4-a716-446655440000"
  • Prefixed random: "req_abc123xyz"
  • ULID: "01ARZ3NDEKTSV4RRFFQ69G5FAV"

The id field MUST NOT be:

  • Null
  • Empty string
  • Numeric (to avoid JSON precision issues)
  • An object or array

Function names MUST use dot notation: <service>.<action>

Examples:

  • orders.create
  • users.get
  • inventory.reserve

Function names beginning with vend. are reserved. See System Functions.

Function names are case-sensitive. Implementations SHOULD use lowercase with underscores for multi-word actions: orders.get_by_customer.


A Vend response is a JSON object with the following structure:

{
"protocol": { "name": "vend", "version": "0.1.0" },
"id": "req_abc123",
"result": { },
"meta": { }
}
FieldTypeRequiredDescription
protocolstringYesProtocol identifier and version
idstringYesEchoed from request. MUST correlate response to request.
resultanyConditionalFunction return value. MUST be present on success.
errorsarrayConditionalArray of error objects. Present when request fails.
metaobjectNoResponse metadata
asyncobjectNoAsync operation status. See Async.

On success, result contains the function’s return value. The type depends on the function:

  • Object: { "order_id": 123 }
  • Array: [{ "id": 1 }, { "id": 2 }]
  • Scalar: 42, "ok", true
  • Null: When function returns nothing

On error, result MUST be null.

A response MUST contain exactly one of:

  • result with value (success)
  • errors with array of error objects (failure)

On error, result MUST be null. The errors array MUST contain at least one error.

See Errors for error object structure.

OPTIONAL metadata about the response:

FieldTypeDescription
nodestringIdentifier of the server node that handled the request

Note: Server-side processing duration is provided via the Tracing Extension. Rate limiting information is provided via the Rate Limit Extension.

Implementations MAY add additional fields to meta.


When a request cannot be parsed as valid JSON:

{
"protocol": { "name": "vend", "version": "0.1.0" },
"id": null,
"result": null,
"errors": [
{
"code": "PARSE_ERROR",
"message": "Invalid JSON: unexpected end of input",
"retryable": false,
"source": {
"position": 52
}
}
]
}

The id field MUST be null when the request’s id could not be determined.

The source.position field SHOULD contain the byte offset where parsing failed, if available.


When using HTTP transport:

AspectConvention
MethodMUST use POST
Content-TypeMUST be application/json
EndpointService-defined (e.g., /vend, /rpc)
HTTP StatusMUST use 200 for all Vend responses

HTTP status codes SHOULD NOT indicate Vend-level errors. Use the error/errors field.

Exception: Transport-level errors (502, 503, 504) indicate the request never reached the Vend handler.

When using message queue transport:

AspectConvention
Message formatMUST be JSON-encoded Vend request
CorrelationMUST use message correlation ID matching Vend id
Reply queueSHOULD specify in message properties

{
"protocol": { "name": "vend", "version": "0.1.0" },
"id": "req_001",
"call": {
"function": "health.check",
"version": "1"
}
}
{
"protocol": { "name": "vend", "version": "0.1.0" },
"id": "req_001",
"result": { "status": "healthy" }
}
{
"protocol": { "name": "vend", "version": "0.1.0" },
"id": "req_xyz789",
"call": {
"function": "orders.create",
"version": "2",
"arguments": {
"customer_id": 42,
"items": [
{ "sku": "WIDGET-01", "quantity": 2 }
]
}
},
"context": {
"caller": "checkout-service"
},
"extensions": [
{
"urn": "urn:vnd:ext:deadline",
"options": { "value": 5, "unit": "second" }
},
{
"urn": "urn:vnd:ext:tracing",
"options": {
"trace_id": "tr_8f3a2b1c",
"span_id": "sp_4d5e6f",
"parent_span_id": "sp_1a2b3c"
}
}
]
}
{
"protocol": { "name": "vend", "version": "0.1.0" },
"id": "req_xyz789",
"result": {
"order_id": 12345,
"status": "pending",
"created_at": "2024-01-15T10:30:00Z"
},
"meta": {
"node": "orders-api-2"
}
}