wortic / watp-sdk
PHP SDK for the Wortic Autonomous Trade Protocol (WATP) — autonomous Agent-to-Agent commerce
Requires
- php: >=8.2
- ext-curl: *
- ext-json: *
- ext-openssl: *
Requires (Dev)
- phpunit/phpunit: ^11.0
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
- Docs (EN): https://watp.wortic.com/en/docs/
- Docs (PT-BR): https://watp.wortic.com/pt-br/docs/
- Docs (ES): https://watp.wortic.com/es/docs/
- Site: https://watp.wortic.com
- Wortic: https://wortic.com.br
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
- Docs (EN): https://watp.wortic.com/en/docs/
- Docs (PT-BR): https://watp.wortic.com/pt-br/docs/
- Docs (ES): https://watp.wortic.com/es/docs/
- Site: https://watp.wortic.com
- Wortic: https://wortic.com.br
Licenca
MIT License. Copyright 2025 Wortic.