Recipe Registry API

HTTP API endpoints for recipe registry server

Recipe Registry API

HTTP API endpoints for the recipe registry server started via praisonai serve registry.

Base URL + Playground

bash
# Start registry server
praisonai serve registry --port 7777

Base URL: http://127.0.0.1:7777

Endpoints

GET /healthz

Health check endpoint.

ParamField none

No parameters required.

curl
curl http://127.0.0.1:7777/healthz
Python
import requests

response = requests.get("http://127.0.0.1:7777/healthz")
health = response.json()
print(f"Status: {health['status']}")
print(f"Auth required: {health['auth_required']}")
JavaScript
const response = await fetch("http://127.0.0.1:7777/healthz");
const health = await response.json();
console.log(`Status: ${health.status}`);

Response:

json
{
  "status": "healthy",
  "auth_required": true,
  "read_only": false,
  "version": "1.0.0"
}

GET /v1/recipes

List all recipes in the registry.

ParamField string

Filter by tags (comma-separated)

ParamField integer

Maximum number of results (default: 50)

ParamField integer

Offset for pagination (default: 0)

curl
curl http://127.0.0.1:7777/v1/recipes
Python
import requests

response = requests.get("http://127.0.0.1:7777/v1/recipes")
data = response.json()
for recipe in data["recipes"]:
    print(f"- {recipe['name']} v{recipe['version']}")
JavaScript
const response = await fetch("http://127.0.0.1:7777/v1/recipes");
const { recipes } = await response.json();
recipes.forEach(r => console.log(`- ${r.name} v${r.version}`));

Response:

json
{
  "recipes": [
    {
      "name": "my-agent",
      "version": "1.0.0",
      "description": "A helpful AI agent",
      "tags": ["agent", "assistant"]
    }
  ],
  "total": 1
}

GET /v1/recipes/{name}

Get information about a specific recipe.

name string

Recipe name

curl
curl http://127.0.0.1:7777/v1/recipes/my-agent
Python
import requests

response = requests.get("http://127.0.0.1:7777/v1/recipes/my-agent")
info = response.json()
print(f"Latest: {info['latest']}")
print(f"Versions: {list(info['versions'].keys())}")

Response:

json
{
  "name": "my-agent",
  "latest": "1.0.0",
  "versions": {
    "1.0.0": {
      "checksum": "sha256:abc123...",
      "published_at": "2024-01-15T10:30:00Z"
    }
  }
}

GET /v1/recipes/{name}/{version}

Get information about a specific version.

name string

Recipe name

version string

Version string (e.g., “1.0.0”)

curl
curl http://127.0.0.1:7777/v1/recipes/my-agent/1.0.0
Python
import requests

response = requests.get("http://127.0.0.1:7777/v1/recipes/my-agent/1.0.0")
version_info = response.json()
print(f"Checksum: {version_info['checksum']}")

Response:

json
{
  "name": "my-agent",
  "version": "1.0.0",
  "checksum": "sha256:abc123...",
  "published_at": "2024-01-15T10:30:00Z",
  "manifest": {
    "description": "A helpful AI agent",
    "tags": ["agent", "assistant"],
    "author": "praison"
  }
}

GET /v1/recipes/{name}/{version}/download

Download a recipe bundle.

name string

Recipe name

version string

Version string

ParamField string

ETag for conditional download

curl
curl -o my-agent-1.0.0.praison \
  http://127.0.0.1:7777/v1/recipes/my-agent/1.0.0/download
Python
import requests

response = requests.get(
    "http://127.0.0.1:7777/v1/recipes/my-agent/1.0.0/download"
)
with open("my-agent-1.0.0.praison", "wb") as f:
    f.write(response.content)

Response: Binary .praison bundle file

Headers:

  • Content-Type: application/gzip
  • ETag: "sha256:abc123..."

POST /v1/recipes/{name}/{version}

Publish a recipe bundle. Requires authentication if token is configured.

name string

Recipe name

version string

Version string

ParamField string

Bearer token for authentication

ParamField string

Base64-encoded .praison bundle

ParamField boolean

Overwrite existing version (default: false)

curl
# Encode bundle as base64
BUNDLE=$(base64 -i my-agent-1.0.0.praison)

curl -X POST http://127.0.0.1:7777/v1/recipes/my-agent/1.0.0 \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $PRAISONAI_REGISTRY_TOKEN" \
  -d "{\"bundle\": \"$BUNDLE\"}"
Python
import requests
import base64
import os

# Read and encode bundle
with open("my-agent-1.0.0.praison", "rb") as f:
    bundle_b64 = base64.b64encode(f.read()).decode()

response = requests.post(
    "http://127.0.0.1:7777/v1/recipes/my-agent/1.0.0",
    headers={
        "Authorization": f"Bearer {os.environ['PRAISONAI_REGISTRY_TOKEN']}"
    },
    json={"bundle": bundle_b64}
)
result = response.json()
print(f"Published: {result['name']}@{result['version']}")

Response:

json
{
  "ok": true,
  "name": "my-agent",
  "version": "1.0.0",
  "checksum": "sha256:abc123...",
  "published_at": "2024-01-15T10:30:00Z"
}

DELETE /v1/recipes/{name}/{version}

Delete a recipe version. Requires authentication if token is configured.

name string

Recipe name

version string

Version string

ParamField string

Bearer token for authentication

curl
curl -X DELETE http://127.0.0.1:7777/v1/recipes/my-agent/1.0.0 \
  -H "Authorization: Bearer $PRAISONAI_REGISTRY_TOKEN"
Python
import requests
import os

response = requests.delete(
    "http://127.0.0.1:7777/v1/recipes/my-agent/1.0.0",
    headers={
        "Authorization": f"Bearer {os.environ['PRAISONAI_REGISTRY_TOKEN']}"
    }
)
print(f"Deleted: {response.status_code == 200}")

Response:

json
{
  "ok": true,
  "message": "Deleted my-agent@1.0.0"
}

GET /v1/search

Search recipes by query.

ParamField string

Search query (matches name, description, tags)

curl
curl "http://127.0.0.1:7777/v1/search?q=agent"
Python
import requests

response = requests.get(
    "http://127.0.0.1:7777/v1/search",
    params={"q": "agent"}
)
results = response.json()
for r in results:
    print(f"- {r['name']}: {r['description']}")
JavaScript
const response = await fetch("http://127.0.0.1:7777/v1/search?q=agent");
const results = await response.json();
results.forEach(r => console.log(`- ${r.name}: ${r.description}`));

Response:

json
[
  {
    "name": "my-agent",
    "version": "1.0.0",
    "description": "A helpful AI agent",
    "tags": ["agent", "assistant"]
  }
]

Authentication

When the server is started with --token, write operations require authentication:

bash
# Start server with token
praisonai serve registry --token $PRAISONAI_REGISTRY_TOKEN

Header format:

Authorization: Bearer <token>

Protected endpoints:

  • POST /v1/recipes/{name}/{version} – Publish
  • DELETE /v1/recipes/{name}/{version} – Delete

Unprotected endpoints:

  • GET /healthz – Health check
  • GET /v1/recipes – List
  • GET /v1/recipes/{name} – Info
  • GET /v1/recipes/{name}/{version} – Version info
  • GET /v1/recipes/{name}/{version}/download – Download
  • GET /v1/search – Search

Errors

StatusDescription
200Success
201Created (publish)
304Not Modified (ETag match)
400Invalid request
401Unauthorized (missing/invalid token)
404Recipe or version not found
409Conflict (version exists, use force)
500Server error

Error Response:

json
{
  "error": "Recipe not found: my-agent",
  "code": 404
}

CLI Equivalent

bash
# List recipes
praisonai recipe list --registry http://localhost:7777

# Search recipes
praisonai recipe search agent --registry http://localhost:7777

# Publish recipe
praisonai recipe publish ./my-recipe \
  --registry http://localhost:7777 \
  --token $TOKEN

# Pull recipe
praisonai recipe pull my-agent \
  --registry http://localhost:7777 \
  -o ./recipes

Related