Create a counterparty
Creates a counterparty, optionally with addresses right away. The name is unique within the Vault; each address is unique within the Vault (it belongs to at most one counterparty, otherwise matching would be ambiguous). Address networks are validated against the Networks registry.
Retroactive match: existing operations with these addresses (whose counterpartyId is still NULL) automatically get the counterparty assigned; the counts are in the response.
curl -X POST "https://policy-engine-rest.ezig.workers.dev/api/v1/vaults/demo_vault/counterparties" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-d '{
"name": "Binance",
"description": "example_string",
"kind": "exchange",
"tags": [
"example_string"
],
"avatarUri": "example_string",
"color": "#000",
"emoji": "🏦",
"createdById": "example_string",
"addresses": [
{
"network": "tron",
"address": "123 Main St",
"label": "example_string"
}
],
"groupId": "example_string",
"newGroup": {
"code": "example_string",
"name": "John Doe",
"description": "example_string",
"avatarUri": "example_string",
"color": "example_string",
"emoji": "example_string"
}
}'
import requests
import json
url = "https://policy-engine-rest.ezig.workers.dev/api/v1/vaults/demo_vault/counterparties"
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_API_TOKEN"
}
data = {
"name": "Binance",
"description": "example_string",
"kind": "exchange",
"tags": [
"example_string"
],
"avatarUri": "example_string",
"color": "#000",
"emoji": "🏦",
"createdById": "example_string",
"addresses": [
{
"network": "tron",
"address": "123 Main St",
"label": "example_string"
}
],
"groupId": "example_string",
"newGroup": {
"code": "example_string",
"name": "John Doe",
"description": "example_string",
"avatarUri": "example_string",
"color": "example_string",
"emoji": "example_string"
}
}
response = requests.post(url, headers=headers, json=data)
print(response.json())
const response = await fetch("https://policy-engine-rest.ezig.workers.dev/api/v1/vaults/demo_vault/counterparties", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_API_TOKEN"
},
body: JSON.stringify({
"name": "Binance",
"description": "example_string",
"kind": "exchange",
"tags": [
"example_string"
],
"avatarUri": "example_string",
"color": "#000",
"emoji": "🏦",
"createdById": "example_string",
"addresses": [
{
"network": "tron",
"address": "123 Main St",
"label": "example_string"
}
],
"groupId": "example_string",
"newGroup": {
"code": "example_string",
"name": "John Doe",
"description": "example_string",
"avatarUri": "example_string",
"color": "example_string",
"emoji": "example_string"
}
})
});
const data = await response.json();
console.log(data);
package main
import (
"fmt"
"net/http"
"bytes"
"encoding/json"
)
func main() {
data := []byte(`{
"name": "Binance",
"description": "example_string",
"kind": "exchange",
"tags": [
"example_string"
],
"avatarUri": "example_string",
"color": "#000",
"emoji": "🏦",
"createdById": "example_string",
"addresses": [
{
"network": "tron",
"address": "123 Main St",
"label": "example_string"
}
],
"groupId": "example_string",
"newGroup": {
"code": "example_string",
"name": "John Doe",
"description": "example_string",
"avatarUri": "example_string",
"color": "example_string",
"emoji": "example_string"
}
}`)
req, err := http.NewRequest("POST", "https://policy-engine-rest.ezig.workers.dev/api/v1/vaults/demo_vault/counterparties", bytes.NewBuffer(data))
if err != nil {
panic(err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println("Response Status:", resp.Status)
}
require 'net/http'
require 'json'
uri = URI('https://policy-engine-rest.ezig.workers.dev/api/v1/vaults/demo_vault/counterparties')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri)
request['Content-Type'] = 'application/json'
request['Authorization'] = 'Bearer YOUR_API_TOKEN'
request.body = '{
"name": "Binance",
"description": "example_string",
"kind": "exchange",
"tags": [
"example_string"
],
"avatarUri": "example_string",
"color": "#000",
"emoji": "🏦",
"createdById": "example_string",
"addresses": [
{
"network": "tron",
"address": "123 Main St",
"label": "example_string"
}
],
"groupId": "example_string",
"newGroup": {
"code": "example_string",
"name": "John Doe",
"description": "example_string",
"avatarUri": "example_string",
"color": "example_string",
"emoji": "example_string"
}
}'
response = http.request(request)
puts response.body
{
"counterparty": {
"id": "cmr3f41z20001psp7phmyapw3",
"vaultId": "example_string",
"name": "Binance",
"description": "example_string",
"kind": "exchange",
"tagsJson": [
"example_string"
],
"avatarUri": "example_string",
"color": "#000",
"emoji": "🏦",
"archivedAt": "2026-07-02T11:25:15.134000Z",
"createdById": "example_string",
"createdAt": "2026-07-02T11:25:15.134000Z",
"updatedAt": "2026-07-02T11:25:15.134000Z",
"addresses": [
{
"id": "example_string",
"counterpartyId": "example_string",
"network": "tron",
"address": "TExternalBinanceHot1",
"label": "hot wallet",
"createdAt": "2026-07-02T11:25:15.134000Z"
}
]
},
"matched": {
"transfers": 42,
"deposits": 42
}
}
{
"request": {
"id": "cmr3f41z20001psp7phmyapw3",
"vaultId": "example_string",
"action": "example_string",
"status": "example_string",
"initiatorId": "example_string",
"targetType": "example_string",
"targetId": "example_string",
"baseVersion": "example_string",
"payload": "null",
"decisionPolicyId": "example_string",
"decisionPolicyCode": "example_string",
"approvalThreshold": 42,
"resolvedResultId": "example_string",
"resolvedAt": "2026-07-02T11:25:15.134000Z",
"createdAt": "2026-07-02T11:25:15.134000Z",
"updatedAt": "2026-07-02T11:25:15.134000Z",
"approvers": [
{
"id": "example_string",
"userId": "example_string",
"decision": "approve",
"comment": "example_string",
"votedAt": "2026-07-02T11:25:15.134000Z",
"stepIndexesJson": [
42
],
"createdAt": "2026-07-02T11:25:15.134000Z",
"user": {
"id": "example_string",
"name": "John Doe",
"email": "user@example.com",
"username": "John Doe",
"image": "example_string",
"color": "#000",
"emoji": "🦊"
}
}
]
}
}
{
"error": "Bad Request",
"message": "The request contains invalid parameters or malformed data",
"code": 400,
"details": [
{
"field": "email",
"message": "Invalid email format"
}
]
}
{
"error": "Unauthorized",
"message": "Authentication required. Please provide a valid API token",
"code": 401
}
{
"error": "Forbidden",
"message": "You don't have permission to access this resource",
"code": 403
}
{
"error": "Not Found",
"message": "The requested resource was not found",
"code": 404
}
{
"error": "Internal Server Error",
"message": "An unexpected error occurred on the server",
"code": 500,
"requestId": "req_1234567890"
}
/api/v1/vaults/{code}/counterpartiesTarget server for requests. Edit to use your own host.
Session token. Mobile/services. The web uses a cookie.
API key (sent in cookie)
Unique Vault code (slug)
The media type of the request body
Link to the avatar
HEX color
Emoji icon
Initial addresses. Each address is unique within the Vault; a conflict with another counterparty returns 400
Add the counterparty to an EXISTING group right away; a composite chain (create + group_add) is built under a single approval flow. Mutually exclusive with newGroup
Create a NEW group and add the counterparty to it: a create + group_create + group_add chain under a single flow. Mutually exclusive with groupId
Request Preview
Response
Response will appear here after sending the request
Authentication
Bearer token. Session token. Mobile/services. The web uses a cookie.
API Key for authentication. Provide your API key in the cookie.
Path Parameters
Body
BinanceexchangeLink to the avatar
Initial addresses. Each address is unique within the Vault; a conflict with another counterparty returns 400
Add the counterparty to an EXISTING group right away; a composite chain (create + group_add) is built under a single approval flow. Mutually exclusive with newGroup
Create a NEW group and add the counterparty to it: a create + group_create + group_add chain under a single flow. Mutually exclusive with groupId