Skip to content

REST API Reference

Complete reference for the Phony Cloud REST API.

Base URL

https://api.phony.cloud/v1

Authentication

All API requests require authentication via Bearer token:

bash
curl -H "Authorization: Bearer $PHONY_API_TOKEN" \
     https://api.phony.cloud/v1/models

Get your API token from the Dashboard → Settings → API Keys.


API Versioning

The API uses URL-based versioning:

VersionStatusEnd of Life
v1Current-

Breaking changes result in a new version. Non-breaking changes (new fields, endpoints) are added to the current version.


Rate Limits

PlanRequests/minuteBurst
Free6010
Starter30050
Team1,000100
Business5,000500

Rate limit headers are included in every response:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 847
X-RateLimit-Reset: 1706745600

Common Response Formats

Success Response

json
{
  "data": { ... },
  "meta": {
    "request_id": "req_abc123",
    "timestamp": "2026-01-31T10:00:00Z"
  }
}

Error Response

json
{
  "error": {
    "code": "validation_error",
    "message": "Invalid input",
    "details": [
      { "field": "count", "message": "must be positive integer" }
    ]
  },
  "meta": {
    "request_id": "req_abc123",
    "timestamp": "2026-01-31T10:00:00Z"
  }
}

Error Codes

CodeHTTP StatusDescription
unauthorized401Invalid or missing API token
forbidden403Insufficient permissions
not_found404Resource not found
validation_error422Invalid request parameters
rate_limit_exceeded429Too many requests
internal_error500Server error

Endpoints

Generation

POST /generate

Generate synthetic data from a schema.

Request:

json
{
  "schema": {
    "generators": {
      "first_name": {
        "type": "model",
        "source": "tr_TR/first_names",
        "generation": { "mode": "word" }
      },
      "last_name": {
        "type": "model",
        "source": "tr_TR/last_names",
        "generation": { "mode": "word" }
      },
      "email": {
        "type": "template",
        "pattern": "{{lowercase(first_name)}}.{{lowercase(last_name)}}@example.com"
      }
    },
    "output": ["first_name", "last_name", "email"]
  },
  "count": 100,
  "seed": 12345,
  "format": "json"
}

Parameters:

ParameterTypeRequiredDescription
schemaobjectYesPDL schema definition
countintegerYesNumber of records (1-100,000)
seedintegerNoRandom seed for determinism
formatstringNoOutput format: json, csv, ndjson

Response:

json
{
  "data": {
    "records": [
      {
        "first_name": "Mehmet",
        "last_name": "Yılmaz",
        "email": "mehmet.yilmaz@example.com"
      },
      {
        "first_name": "Ayşe",
        "last_name": "Kaya",
        "email": "ayse.kaya@example.com"
      }
    ],
    "count": 100,
    "seed": 12345
  },
  "meta": {
    "request_id": "req_abc123",
    "generation_time_ms": 45
  }
}

Example:

bash
curl -X POST https://api.phony.cloud/v1/generate \
  -H "Authorization: Bearer $PHONY_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "schema": {
      "generators": {
        "name": {
          "type": "model",
          "source": "tr_TR/first_names",
          "generation": { "mode": "word" }
        }
      },
      "output": ["name"]
    },
    "count": 10
  }'

Models

GET /models

List available models.

Query Parameters:

ParameterTypeDescription
localestringFilter by locale (e.g., tr_TR)
typestringFilter by type: builtin, custom, all
pageintegerPage number (default: 1)
per_pageintegerItems per page (default: 20, max: 100)

Response:

json
{
  "data": {
    "models": [
      {
        "id": "tr_TR/first_names",
        "name": "Turkish First Names",
        "locale": "tr_TR",
        "type": "builtin",
        "ngram_order": 3,
        "token_type": "char",
        "created_at": "2026-01-01T00:00:00Z"
      },
      {
        "id": "custom/company_names",
        "name": "Custom Company Names",
        "locale": "tr_TR",
        "type": "custom",
        "ngram_order": 3,
        "token_type": "char",
        "created_at": "2026-01-15T10:30:00Z"
      }
    ],
    "total": 45,
    "page": 1,
    "per_page": 20
  }
}

GET /models/:id

Get model details.

Response:

json
{
  "data": {
    "id": "tr_TR/first_names",
    "name": "Turkish First Names",
    "locale": "tr_TR",
    "type": "builtin",
    "ngram_order": 3,
    "token_type": "char",
    "token_count": 29,
    "ngram_count": 1245,
    "created_at": "2026-01-01T00:00:00Z",
    "updated_at": "2026-01-01T00:00:00Z"
  }
}

POST /models

Upload a custom model.

Request (multipart/form-data):

FieldTypeRequiredDescription
filefileYes.phony model file
namestringYesModel name
descriptionstringNoModel description

Response:

json
{
  "data": {
    "id": "custom/my-model",
    "name": "My Custom Model",
    "locale": "tr_TR",
    "type": "custom",
    "ngram_order": 3,
    "created_at": "2026-01-31T10:00:00Z"
  }
}

DELETE /models/:id

Delete a custom model.

Response:

json
{
  "data": {
    "deleted": true,
    "id": "custom/my-model"
  }
}

Sync Jobs

GET /sync/jobs

List sync jobs.

Query Parameters:

ParameterTypeDescription
statusstringFilter: pending, running, completed, failed
pageintegerPage number
per_pageintegerItems per page

Response:

json
{
  "data": {
    "jobs": [
      {
        "id": "job_abc123",
        "name": "production-to-staging",
        "status": "completed",
        "source": "postgresql://prod.example.com/app",
        "target": "postgresql://staging.example.com/app",
        "tables": ["users", "orders", "products"],
        "rows_processed": 150000,
        "started_at": "2026-01-31T09:00:00Z",
        "completed_at": "2026-01-31T09:05:32Z"
      }
    ]
  }
}

POST /sync/jobs

Create and run a sync job.

Request:

json
{
  "name": "production-to-staging",
  "source": {
    "type": "postgresql",
    "connection_string": "postgresql://user:pass@prod.example.com/app"
  },
  "target": {
    "type": "postgresql",
    "connection_string": "postgresql://user:pass@staging.example.com/app"
  },
  "tables": [
    {
      "name": "users",
      "columns": {
        "first_name": { "generator": "tr_TR/first_names" },
        "last_name": { "generator": "tr_TR/last_names" },
        "email": { "generator": "template", "pattern": "{{uuid}}@example.com" },
        "created_at": { "preserve": true }
      }
    }
  ]
}

GET /sync/jobs/:id

Get sync job details.

DELETE /sync/jobs/:id

Cancel or delete a sync job.


Snapshots

GET /snapshots

List snapshots.

Response:

json
{
  "data": {
    "snapshots": [
      {
        "id": "snap_abc123",
        "name": "pre-migration",
        "database": "staging",
        "size_bytes": 1073741824,
        "tables": ["users", "orders", "products"],
        "created_at": "2026-01-30T15:00:00Z",
        "expires_at": "2026-02-28T15:00:00Z"
      }
    ]
  }
}

POST /snapshots

Create a snapshot.

Request:

json
{
  "name": "pre-migration",
  "database": "staging",
  "tables": ["users", "orders", "products"],
  "expires_in_days": 30
}

POST /snapshots/:id/restore

Restore from a snapshot.

Request:

json
{
  "target_database": "staging",
  "overwrite": true
}

DELETE /snapshots/:id

Delete a snapshot.


Mock API

GET /mock/endpoints

List mock API endpoints.

Response:

json
{
  "data": {
    "endpoints": [
      {
        "id": "ep_abc123",
        "path": "/api/users",
        "method": "GET",
        "schema": "users.pdl.json",
        "url": "https://mock.phony.cloud/ep_abc123/api/users",
        "requests_today": 1523,
        "created_at": "2026-01-15T10:00:00Z"
      }
    ]
  }
}

POST /mock/endpoints

Create a mock endpoint.

Request:

json
{
  "path": "/api/users",
  "method": "GET",
  "schema": {
    "generators": {
      "id": { "type": "logic", "algorithm": "uuid_v7" },
      "name": { "type": "model", "source": "tr_TR/full_names", "generation": { "mode": "word" } },
      "email": { "type": "template", "pattern": "{{lowercase(name)}}@example.com" }
    },
    "output": ["id", "name", "email"]
  },
  "response": {
    "count": 10,
    "wrapper": { "data": "{{records}}", "total": "{{count}}" }
  }
}

DELETE /mock/endpoints/:id

Delete a mock endpoint.


Organizations

GET /org

Get current organization.

Response:

json
{
  "data": {
    "id": "org_abc123",
    "name": "Acme Corp",
    "plan": "team",
    "members": 5,
    "usage": {
      "sync_jobs": { "used": 8, "limit": 15 },
      "endpoints": { "used": 45, "limit": 150 },
      "snapshots": { "used": 12, "limit": 50 },
      "api_calls": { "used": 8500, "limit": 100000 }
    },
    "billing_cycle_end": "2026-02-15T00:00:00Z"
  }
}

GET /org/members

List organization members.

POST /org/members

Invite a member.

DELETE /org/members/:id

Remove a member.


SDKs

Official SDKs are available for common languages:

LanguagePackageInstallation
PHPphonycloud/phony-cloudcomposer require phonycloud/phony-cloud
Pythonphony-cloudpip install phony-cloud
JavaScript/TypeScript@phony/cloudnpm install @phony/cloud
Gogithub.com/phonycloud/phony-gogo get github.com/phonycloud/phony-go

PHP SDK Example

php
use Phonyland\Cloud\PhonyCloud;

$client = new PhonyCloud(getenv('PHONY_API_TOKEN'));

// Generate data
$result = $client->generate([
    'schema' => [
        'generators' => [
            'name' => ['type' => 'model', 'source' => 'tr_TR/first_names', 'generation' => ['mode' => 'word']]
        ],
        'output' => ['name']
    ],
    'count' => 100
]);

foreach ($result->records as $record) {
    echo $record->name . "\n";
}

Python SDK Example

python
from phony_cloud import PhonyCloud
import os

client = PhonyCloud(os.environ['PHONY_API_TOKEN'])

# Generate data
result = client.generate(
    schema={
        'generators': {
            'name': {'type': 'model', 'source': 'tr_TR/first_names', 'generation': {'mode': 'word'}}
        },
        'output': ['name']
    },
    count=100
)

for record in result.records:
    print(record['name'])

Webhooks

Configure webhooks in Dashboard → Settings → Webhooks.

Events

EventDescription
sync.startedSync job started
sync.completedSync job completed
sync.failedSync job failed
snapshot.createdSnapshot created
snapshot.restoredSnapshot restored

Payload

json
{
  "event": "sync.completed",
  "timestamp": "2026-01-31T10:00:00Z",
  "data": {
    "job_id": "job_abc123",
    "name": "production-to-staging",
    "rows_processed": 150000,
    "duration_seconds": 332
  }
}

Signature Verification

Verify webhook authenticity using the X-Phony-Signature header:

php
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_PHONY_SIGNATURE'];
$expected = hash_hmac('sha256', $payload, $webhookSecret);

if (!hash_equals($expected, $signature)) {
    http_response_code(401);
    exit('Invalid signature');
}

Phony Cloud Platform Specification