wortic/watp-sdk

PHP SDK for the Wortic Autonomous Trade Protocol (WATP) — autonomous Agent-to-Agent commerce

Maintainers

Package info

github.com/williamschonswortic/watp

pkg:composer/wortic/watp-sdk

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

dev-main 2026-04-13 20:23 UTC

This package is not auto-updated.

Last update: 2026-04-14 19:12:38 UTC


README

WATP (Wortic Autonomous Trade Protocol) is an open protocol for autonomous commerce between AI agents. Agents from different companies discover demand, negotiate prices, exchange counterproposals and close digitally signed contracts with zero human intervention. Every message is chained via SHA-256 hashing. Final agreements are signed with X.509 certificates.

Installation

composer require wortic/watp-sdk

Quick Start

use Wortic\WATP\Client;
use Wortic\WATP\Message;

$client = new Client([
    'node_url' => 'https://site-a.wortic.com/api',
    'cert_path' => '/path/to/cert.pem',
    'key_path' => '/path/to/key.pem',
]);

// Broadcast interest
$interest = Message::interest([
    'product' => 'Patch Cord Cat6 UTP 1.5m',
    'quantity' => 500,
    'max_unit_price' => 15.00,
    'currency' => 'BRL',
    'delivery_deadline' => '2025-05-15',
]);

$response = $client->send($interest);

Examples

Minimal examples for sending a WATP message via the REST API.

PHP

$ch = curl_init('https://site-a.wortic.com/api/v1/messages');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'Authorization: Bearer <token>',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'type' => 'interest',
        'product' => 'Patch Cord Cat6 UTP 1.5m',
        'quantity' => 500,
        'max_unit_price' => 15.00,
    ]),
    CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
curl_close($ch);

Python

import requests

r = requests.post(
    "https://site-a.wortic.com/api/v1/messages",
    headers={"Authorization": "Bearer <token>"},
    json={"type": "interest", "product": "Patch Cord Cat6 UTP 1.5m", "quantity": 500, "max_unit_price": 15.00},
)
print(r.json())

Node.js

const res = await fetch("https://site-a.wortic.com/api/v1/messages", {
  method: "POST",
  headers: { "Content-Type": "application/json", "Authorization": "Bearer <token>" },
  body: JSON.stringify({ type: "interest", product: "Patch Cord Cat6 UTP 1.5m", quantity: 500, max_unit_price: 15.0 }),
});
const data = await res.json();

Ruby

require 'net/http'
require 'json'

uri = URI("https://site-a.wortic.com/api/v1/messages")
req = Net::HTTP::Post.new(uri, "Content-Type" => "application/json", "Authorization" => "Bearer <token>")
req.body = { type: "interest", product: "Patch Cord Cat6 UTP 1.5m", quantity: 500, max_unit_price: 15.0 }.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
puts res.body

Go

package main

import (
    "bytes"
    "fmt"
    "net/http"
)

func main() {
    body := []byte(`{"type":"interest","product":"Patch Cord Cat6 UTP 1.5m","quantity":500,"max_unit_price":15.00}`)
    req, _ := http.NewRequest("POST", "https://site-a.wortic.com/api/v1/messages", bytes.NewBuffer(body))
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("Authorization", "Bearer <token>")
    resp, _ := http.DefaultClient.Do(req)
    defer resp.Body.Close()
    fmt.Println(resp.Status)
}

Java

import java.net.http.*;
import java.net.URI;

var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
    .uri(URI.create("https://site-a.wortic.com/api/v1/messages"))
    .header("Content-Type", "application/json")
    .header("Authorization", "Bearer <token>")
    .POST(HttpRequest.BodyPublishers.ofString(
        "{\"type\":\"interest\",\"product\":\"Patch Cord Cat6 UTP 1.5m\",\"quantity\":500,\"max_unit_price\":15.00}"))
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());

C#

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer <token>");
var content = new StringContent(
    "{\"type\":\"interest\",\"product\":\"Patch Cord Cat6 UTP 1.5m\",\"quantity\":500,\"max_unit_price\":15.00}",
    System.Text.Encoding.UTF8, "application/json");
var response = await client.PostAsync("https://site-a.wortic.com/api/v1/messages", content);
Console.WriteLine(await response.Content.ReadAsStringAsync());

Kotlin

val client = OkHttpClient()
val body = """{"type":"interest","product":"Patch Cord Cat6 UTP 1.5m","quantity":500,"max_unit_price":15.00}"""
    .toRequestBody("application/json".toMediaType())
val request = Request.Builder()
    .url("https://site-a.wortic.com/api/v1/messages")
    .addHeader("Authorization", "Bearer <token>")
    .post(body).build()
val response = client.newCall(request).execute()
println(response.body?.string())

Swift

var request = URLRequest(url: URL(string: "https://site-a.wortic.com/api/v1/messages")!)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("Bearer <token>", forHTTPHeaderField: "Authorization")
request.httpBody = #"{"type":"interest","product":"Patch Cord Cat6 UTP 1.5m","quantity":500,"max_unit_price":15.00}"#.data(using: .utf8)
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)

C

#include <curl/curl.h>

int main(void) {
    CURL *curl = curl_easy_init();
    struct curl_slist *headers = NULL;
    headers = curl_slist_append(headers, "Content-Type: application/json");
    headers = curl_slist_append(headers, "Authorization: Bearer <token>");
    curl_easy_setopt(curl, CURLOPT_URL, "https://site-a.wortic.com/api/v1/messages");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS,
        "{\"type\":\"interest\",\"product\":\"Patch Cord Cat6 UTP 1.5m\",\"quantity\":500,\"max_unit_price\":15.00}");
    curl_easy_perform(curl);
    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);
    return 0;
}

C++

#include <curl/curl.h>
#include <string>

int main() {
    CURL *curl = curl_easy_init();
    struct curl_slist *headers = nullptr;
    headers = curl_slist_append(headers, "Content-Type: application/json");
    headers = curl_slist_append(headers, "Authorization: Bearer <token>");
    std::string payload = R"({"type":"interest","product":"Patch Cord Cat6 UTP 1.5m","quantity":500,"max_unit_price":15.00})";
    curl_easy_setopt(curl, CURLOPT_URL, "https://site-a.wortic.com/api/v1/messages");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload.c_str());
    curl_easy_perform(curl);
    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);
    return 0;
}

Assembly (x86_64 Linux)

; x86_64 Linux syscall approach
; HTTP requires a TCP socket (socket, connect, write, read syscalls).
; The data section holds the raw HTTP request.

section .data
    request db "POST /api/v1/messages HTTP/1.1", 0x0d, 0x0a
            db "Host: site-a.wortic.com", 0x0d, 0x0a
            db "Content-Type: application/json", 0x0d, 0x0a
            db "Authorization: Bearer <token>", 0x0d, 0x0a
            db "Content-Length: 92", 0x0d, 0x0a
            db 0x0d, 0x0a
            db '{"type":"interest","product":"Patch Cord Cat6 UTP 1.5m","quantity":500,"max_unit_price":15}', 0

; Full implementation requires socket(), connect() to port 443 with TLS,
; write() the request buffer, and read() the response.
; Production use: link against libcurl or OpenSSL and call from asm.

cURL

curl -X POST https://site-a.wortic.com/api/v1/messages \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{"type":"interest","product":"Patch Cord Cat6 UTP 1.5m","quantity":500,"max_unit_price":15.00}'

State Machine

Every negotiation follows a six-state lifecycle:

State Description
HASH_INTEREST An agent broadcasts a purchase or supply interest to the network.
HASH_PROPOSAL A counterpart agent responds with a concrete offer.
HASH_COUNTER Either side sends a counterproposal with adjusted terms.
HASH_WAITING_HUMAN The negotiation exceeds agent authority and requires human approval.
HASH_CONCLUDED Both parties accepted the terms. A signed contract is generated.
HASH_CANCELLED One side rejected or the negotiation timed out.

API Endpoints

Method Path Description
POST /api/v1/messages Send a new message
GET /api/v1/messages/{id} Get message by ID
GET /api/v1/negotiations List negotiations
GET /api/v1/negotiations/{id} Get negotiation detail
POST /api/v1/negotiations/{id}/approve Human approval
GET /api/v1/health Health check

Links

License

MIT License. Copyright 2025 Wortic.

WATP SDK (Portugues)

WATP (Wortic Autonomous Trade Protocol) e um protocolo aberto para comercio autonomo entre agentes de IA. Agentes de diferentes empresas descobrem demanda, negociam precos, trocam contrapropostas e fecham contratos assinados digitalmente sem intervencao humana. Cada mensagem e encadeada via hash SHA-256. Acordos finais sao assinados com certificados X.509.

Instalacao

composer require wortic/watp-sdk

Inicio Rapido

use Wortic\WATP\Client;
use Wortic\WATP\Message;

$client = new Client([
    'node_url' => 'https://site-a.wortic.com/api',
    'cert_path' => '/path/to/cert.pem',
    'key_path' => '/path/to/key.pem',
]);

// Broadcast de interesse
$interest = Message::interest([
    'product' => 'Patch Cord Cat6 UTP 1.5m',
    'quantity' => 500,
    'max_unit_price' => 15.00,
    'currency' => 'BRL',
    'delivery_deadline' => '2025-05-15',
]);

$response = $client->send($interest);

Exemplos

Exemplos minimos para enviar uma mensagem WATP via API REST.

PHP

$ch = curl_init('https://site-a.wortic.com/api/v1/messages');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'Authorization: Bearer <token>',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'type' => 'interest',
        'product' => 'Patch Cord Cat6 UTP 1.5m',
        'quantity' => 500,
        'max_unit_price' => 15.00,
    ]),
    CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
curl_close($ch);

Python

import requests

r = requests.post(
    "https://site-a.wortic.com/api/v1/messages",
    headers={"Authorization": "Bearer <token>"},
    json={"type": "interest", "product": "Patch Cord Cat6 UTP 1.5m", "quantity": 500, "max_unit_price": 15.00},
)
print(r.json())

Node.js

const res = await fetch("https://site-a.wortic.com/api/v1/messages", {
  method: "POST",
  headers: { "Content-Type": "application/json", "Authorization": "Bearer <token>" },
  body: JSON.stringify({ type: "interest", product: "Patch Cord Cat6 UTP 1.5m", quantity: 500, max_unit_price: 15.0 }),
});
const data = await res.json();

Ruby

require 'net/http'
require 'json'

uri = URI("https://site-a.wortic.com/api/v1/messages")
req = Net::HTTP::Post.new(uri, "Content-Type" => "application/json", "Authorization" => "Bearer <token>")
req.body = { type: "interest", product: "Patch Cord Cat6 UTP 1.5m", quantity: 500, max_unit_price: 15.0 }.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
puts res.body

Go

package main

import (
    "bytes"
    "fmt"
    "net/http"
)

func main() {
    body := []byte(`{"type":"interest","product":"Patch Cord Cat6 UTP 1.5m","quantity":500,"max_unit_price":15.00}`)
    req, _ := http.NewRequest("POST", "https://site-a.wortic.com/api/v1/messages", bytes.NewBuffer(body))
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("Authorization", "Bearer <token>")
    resp, _ := http.DefaultClient.Do(req)
    defer resp.Body.Close()
    fmt.Println(resp.Status)
}

Java

import java.net.http.*;
import java.net.URI;

var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
    .uri(URI.create("https://site-a.wortic.com/api/v1/messages"))
    .header("Content-Type", "application/json")
    .header("Authorization", "Bearer <token>")
    .POST(HttpRequest.BodyPublishers.ofString(
        "{\"type\":\"interest\",\"product\":\"Patch Cord Cat6 UTP 1.5m\",\"quantity\":500,\"max_unit_price\":15.00}"))
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());

C#

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer <token>");
var content = new StringContent(
    "{\"type\":\"interest\",\"product\":\"Patch Cord Cat6 UTP 1.5m\",\"quantity\":500,\"max_unit_price\":15.00}",
    System.Text.Encoding.UTF8, "application/json");
var response = await client.PostAsync("https://site-a.wortic.com/api/v1/messages", content);
Console.WriteLine(await response.Content.ReadAsStringAsync());

Kotlin

val client = OkHttpClient()
val body = """{"type":"interest","product":"Patch Cord Cat6 UTP 1.5m","quantity":500,"max_unit_price":15.00}"""
    .toRequestBody("application/json".toMediaType())
val request = Request.Builder()
    .url("https://site-a.wortic.com/api/v1/messages")
    .addHeader("Authorization", "Bearer <token>")
    .post(body).build()
val response = client.newCall(request).execute()
println(response.body?.string())

Swift

var request = URLRequest(url: URL(string: "https://site-a.wortic.com/api/v1/messages")!)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("Bearer <token>", forHTTPHeaderField: "Authorization")
request.httpBody = #"{"type":"interest","product":"Patch Cord Cat6 UTP 1.5m","quantity":500,"max_unit_price":15.00}"#.data(using: .utf8)
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)

C

#include <curl/curl.h>

int main(void) {
    CURL *curl = curl_easy_init();
    struct curl_slist *headers = NULL;
    headers = curl_slist_append(headers, "Content-Type: application/json");
    headers = curl_slist_append(headers, "Authorization: Bearer <token>");
    curl_easy_setopt(curl, CURLOPT_URL, "https://site-a.wortic.com/api/v1/messages");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS,
        "{\"type\":\"interest\",\"product\":\"Patch Cord Cat6 UTP 1.5m\",\"quantity\":500,\"max_unit_price\":15.00}");
    curl_easy_perform(curl);
    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);
    return 0;
}

C++

#include <curl/curl.h>
#include <string>

int main() {
    CURL *curl = curl_easy_init();
    struct curl_slist *headers = nullptr;
    headers = curl_slist_append(headers, "Content-Type: application/json");
    headers = curl_slist_append(headers, "Authorization: Bearer <token>");
    std::string payload = R"({"type":"interest","product":"Patch Cord Cat6 UTP 1.5m","quantity":500,"max_unit_price":15.00})";
    curl_easy_setopt(curl, CURLOPT_URL, "https://site-a.wortic.com/api/v1/messages");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload.c_str());
    curl_easy_perform(curl);
    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);
    return 0;
}

Assembly (x86_64 Linux)

; x86_64 Linux syscall
; HTTP requer socket TCP (syscalls socket, connect, write, read).
; A secao .data contem a requisicao HTTP crua.

section .data
    request db "POST /api/v1/messages HTTP/1.1", 0x0d, 0x0a
            db "Host: site-a.wortic.com", 0x0d, 0x0a
            db "Content-Type: application/json", 0x0d, 0x0a
            db "Authorization: Bearer <token>", 0x0d, 0x0a
            db "Content-Length: 92", 0x0d, 0x0a
            db 0x0d, 0x0a
            db '{"type":"interest","product":"Patch Cord Cat6 UTP 1.5m","quantity":500,"max_unit_price":15}', 0

; Implementacao completa requer socket(), connect() na porta 443 com TLS,
; write() do buffer de requisicao e read() da resposta.
; Em producao: linkar contra libcurl ou OpenSSL e chamar a partir do asm.

cURL

curl -X POST https://site-a.wortic.com/api/v1/messages \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{"type":"interest","product":"Patch Cord Cat6 UTP 1.5m","quantity":500,"max_unit_price":15.00}'

Maquina de Estados

Toda negociacao segue um ciclo de seis estados:

Estado Descricao
HASH_INTEREST Um agente transmite interesse de compra ou fornecimento para a rede.
HASH_PROPOSAL Um agente contraparte responde com uma oferta concreta.
HASH_COUNTER Qualquer lado envia uma contraproposta com termos ajustados.
HASH_WAITING_HUMAN A negociacao excedeu a autoridade do agente e requer aprovacao humana.
HASH_CONCLUDED Ambas as partes aceitaram os termos. Um contrato assinado e gerado.
HASH_CANCELLED Um dos lados rejeitou ou a negociacao expirou.

Endpoints da API

Metodo Caminho Descricao
POST /api/v1/messages Enviar nova mensagem
GET /api/v1/messages/{id} Obter mensagem por ID
GET /api/v1/negotiations Listar negociacoes
GET /api/v1/negotiations/{id} Detalhe da negociacao
POST /api/v1/negotiations/{id}/approve Aprovacao humana
GET /api/v1/health Health check

Links

Licenca

MIT License. Copyright 2025 Wortic.