REST API
Endpoints that scripts call to control a running pogi.
All paths are on the main port, http://localhost:7644 by default. Bodies and answers are JSON unless noted. The cloud APIs themselves (S3, SQS, Pub/Sub and so on) are not listed here. Call those with the usual SDKs and CLIs.
pogi's own endpoints do not show up in Activity.
| Method and path | Purpose |
|---|---|
GET /_pogi/ | Version, uptime, IAM (who may do what) mode and every service. |
GET /_pogi/ | Recent calls, with filters. |
GET /_pogi/ | One call with headers and bodies. |
GET /_pogi/ | Resource tables of every service, or one. |
GET /_pogi/ | The detail of one resource. |
POST /_pogi/ | Delete state, for all services or some. |
POST /moto-api/ | The way moto (a Python AWS mock) and LocalStack reset. |
GET /_pogi/ | Saved snapshots. |
POST /_pogi/ | Save all state under a name. |
POST /_pogi/ | Replace the state with a snapshot. |
GET /_pogi/ | Get the snapshot file. |
PUT /_pogi/ | Store a snapshot file under a name. |
DELETE /_pogi/ | Remove a snapshot. |
GET /_pogi/ | Active fault-injection rules. |
POST /_pogi/ | Add a rule. |
DELETE /_pogi/ | Remove one rule. |
DELETE /_pogi/ | Clear every rule. |
GET /_aws/ | Read a queue without receiving. |
GET, DELETE /_aws/ses | Emails sent through SES. |
GET, DELETE /_aws/ | SMS sent through SNS. |
GET, DELETE /_aws/ | Push messages sent through SNS. |
GET /_aws/ | Codes Cognito "sent". |
GET /_localstack/ | LocalStack's health endpoint. |
GET /_localstack/ | LocalStack's info endpoint. |
GET /_localstack/ | State of the init scripts. Leave out the stage for all four. |
GET /_gcp/ | Kubeconfig for a GKE cluster pogi runs. |
/_pogi/mcp | pogi's MCP endpoint. |
Same-origin rule
Writes to /_pogi/api/, /_localstack/, /moto-api/ and the console's form posts answer 403 when the request carries an Origin header that does not match the Host header. Tools such as curl and server-side code send no Origin, so they are not affected. A page in a browser on another origin is.
Status
Get status
GET /_pogi/
Returns the status of pogi. pogi status and pogi wait call it.
curl localhost:7644/_pogi/api/info{
"version": "0.1.0",
"started": "2026-10-13T23:41:35.879922+05:30",
"uptime": 15,
"region": "us-east-1",
"persist": false,
"dataDir": "/home/me/.pogi",
"iam": "off",
"lambda": "auto",
"ready": true,
"services": [
{"name": "s3", "cloud": "aws", "title": "S3", "resources": 1, "requests": 3},
{"name": "sqs", "cloud": "aws", "title": "SQS", "resources": 0, "requests": 0}
]
}uptimeis in seconds.readyistrueonce pogi serves requests. That is after thestartinit hooks and the seed data inpogi.yamlhave run.serviceshas one entry for every enabled service. The example shows two.
Calls and resources
List requests
GET /_pogi/
Returns the recent calls, oldest first, without headers and bodies. pogi keeps the last 1000.
| Query | Type | Default | Meaning |
|---|---|---|---|
limit | number | 200 | The most calls to return. The newest ones are kept. |
after | number | 0 | Only calls with an id above this number. |
service | string | any | Only this service id (the name pogi services prints), such as s3. |
q | string | none | Only calls whose service, operation, path or error contains this text, ignoring case. |
errors | any value | off | Only calls with a status of 400 or above. |
wait | seconds | 0 | Wait for a call newer than after before answering, at most 60. Use it to follow the log. |
curl "localhost:7644/_pogi/api/requests?errors=1&limit=1"[{"id":3,"time":"2026-10-13T23:41:51.597753+05:30","cloud":"aws","service":"s3","op":"GetObject","method":"GET","path":"/000000000000/jobs","status":404,"ms":0.038,"account":"000000000000","region":"us-east-1","requestId":"1f94db90…","principal":"arn:aws:iam::000000000000:root","error":"NoSuchBucket","trace":"1-8f78bfaf-8885d0da627d5eb7ca8d0cad"}]The fields of an entry:
| Field | Meaning |
|---|---|
id | A number that grows with each call. |
time, ms | When the call arrived, and how long it took in milliseconds. |
cloud, service, op | The cloud, service id and operation. |
method, path, status | The HTTP method, path and answer status. |
account, region, requestId, accessKey, principal | Who called, where and as whom. Left out when empty. |
error | The error code, when the call failed. |
chaos | true when a chaos rule changed the call. |
iam | allow or deny: why, when IAM enforcement is on. |
trace | The flow the call belongs to. See Flows and the Map. |
Get one request
GET /_pogi/
Returns one call in full. It adds reqHeaders, reqBody and respBody. The Authorization header shows as [redacted].
curl localhost:7644/_pogi/api/requests/3{"id":3,"service":"s3","op":"GetObject","status":404,"error":"NoSuchBucket","reqHeaders":{"Accept":"*/*","User-Agent":"curl/8.7.1"},"respBody":"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Error><Code>NoSuchBucket</Code>…</Error>", …}- A call that has left the log answers
404with{"error":"request not found (the log keeps the last 1000)"}.
List resources
GET /_pogi/
Returns the resource tables of every service. pogi ls calls it.
| Query | Type | Default | Meaning |
|---|---|---|---|
service | string | all | Only this service id. |
curl "localhost:7644/_pogi/api/resources?service=s3"{"s3":[{"name":"Buckets","columns":["Name","Region","Account","Objects","Size","Versioning","Created"],"rows":[["demo","us-east-1","000000000000","0","0 B","","2026-10-13 18:11:51"]]}]}Get one resource
GET /_pogi/
Returns the detail of one resource.
curl localhost:7644/_pogi/api/resources/s3/Buckets/demo{"account":"000000000000","config":{},"created":"2026-10-13T18:11:51.580874Z","keys":0,"name":"demo","region":"us-east-1","uploads":0,"versioning":""}- If there is no such resource, the answer is
404with{"error":"resource not found"}.
Reset and snapshots
Reset state
POST /_pogi/
Deletes state. pogi reset calls it. The seed data in pogi.yaml is created again afterward.
| Query | Type | Default | Meaning |
|---|---|---|---|
service | string | all | Comma-separated service ids to reset. |
curl -X POST "localhost:7644/_pogi/api/reset?service=s3,sqs"{"reset":["s3","sqs"]}With no service, the answer is {"reset":null}.
Reset all state (moto)
POST /moto-api/
Resets every service, the way moto and LocalStack tools expect.
curl -X POST localhost:7644/moto-api/reset{"status":"ok"}List snapshots
GET /_pogi/
Lists the saved snapshots. See Save and load snapshots.
curl localhost:7644/_pogi/api/snapshots[{"name":"demo","size":13691,"saved":"2026-10-13T23:42:04.620597368+05:30"}]A snapshot name may use letters, digits, ., _ and -. The snapshot calls below answer 400 with {"error":"…"} for a bad name or a failed action.
Save a snapshot
POST /_pogi/
Saves all state under {name}.
curl -X POST localhost:7644/_pogi/api/snapshots/demo{"snapshot":"demo"}Load a snapshot
POST /_pogi/
Replaces the current state with the snapshot {name}.
curl -X POST localhost:7644/_pogi/api/snapshots/demo/load{"snapshot":"demo"}Download a snapshot
GET /_pogi/
Downloads the snapshot file, {name}.json.
curl -o demo.json localhost:7644/_pogi/api/snapshots/demoImport a snapshot
PUT /_pogi/
Stores the request body, a snapshot file, under {name}.
curl -X PUT --data-binary @demo.json localhost:7644/_pogi/api/snapshots/copy{"snapshot":"copy"}Delete a snapshot
DELETE /_pogi/
Deletes the snapshot.
curl -X DELETE localhost:7644/_pogi/api/snapshots/copy{"snapshot":"copy"}Chaos
List chaos rules
GET /_pogi/
Lists the rules. See Inject chaos.
curl localhost:7644/_pogi/api/chaos[{"id":"f2c47b28","service":"dynamodb","probability":0.25,"latencyMs":200,"hits":0}]Add a chaos rule
POST /_pogi/
Adds a rule from a JSON body and returns it with its id.
| Field | Type | Default | Meaning |
|---|---|---|---|
service | string | any | Service to match, as a pattern. |
op | string | any | Operation to match, as a pattern, such as Put*. |
cloud, region, principal, path | string | any | More patterns to match. |
probability | number | 0 | Chance that a matching call is affected, from 0 to 1. 0 means always. |
latencyMs | number | none | Delay to add, in milliseconds. |
status | number | none | HTTP status to answer with. |
code | string | none | Error code to return. |
message | string | none | Error message to return. |
The answer also has id and hits, how often the rule has fired.
curl -X POST -H "content-type: application/json" \
-d '{"service":"dynamodb","latencyMs":200,"probability":0.25}' \
localhost:7644/_pogi/api/chaos{"id":"f2c47b28","service":"dynamodb","probability":0.25,"latencyMs":200,"hits":0}- A body that is not valid JSON answers
400with{"error":"…"}.
Remove a chaos rule
DELETE /_pogi/
Removes one rule.
curl -X DELETE localhost:7644/_pogi/api/chaos/f2c47b28The answer is 204 with no body. If there is no such rule, it is 404 with {"error":"rule not found"}.
Remove all chaos rules
DELETE /_pogi/
Removes every rule. The answer is 204 with no body.
curl -X DELETE localhost:7644/_pogi/api/chaosOutboxes
These endpoints show what pogi captured instead of sending: queue messages, emails, texts, push messages and Cognito codes.
Peek at SQS messages
GET /_aws/
Reads a queue's messages without receiving them. See Migrate from LocalStack.
| Query | Type | Default | Meaning |
|---|---|---|---|
QueueUrl | string | none | The queue URL. |
Region | string | any | The queue's region. pogi finds the queue in any region when it is not given. |
You can also put the queue in the path: GET /_aws/.
curl localhost:7644/_aws/sqs/messages/us-east-1/000000000000/jobs{"messages":[{"MessageId":"12b3bfae-4999-4fd9-aaf6-786d4acdc7ff","Body":"hello","SentTimestamp":"2026-10-13T18:11:57.486148Z","ApproximateReceiveCount":0,"State":"visible"}]}- An unknown queue answers
400with{"error":"QueueDoesNotExist: The specified queue does not exist."}.
List or clear SES emails
GET /_aws/ses and DELETE /_aws/ses
Lists, or clears, the emails sent through SES.
| Query | Type | Default | Meaning |
|---|---|---|---|
id | string | all | Only this message id. On DELETE, it removes only this message. |
email | string | all | Only messages from this sender. Lists only. |
curl localhost:7644/_aws/ses{"messages":[{"Id":"280a2f0e7aae7dab-39f9247e-fa79-4078-8861-977ca26fd24f-000000","Region":"us-east-1","Account":"000000000000","Source":"a@example.com","Destination":{"ToAddresses":["b@example.com"]},"Subject":"hi","Body":{"text_part":"hello there","html_part":""},"Timestamp":"2026-10-13T18:14:04.490798Z"}]}DELETE answers 204. Without id, it removes every message.
List or clear SMS messages
GET /_aws/ and DELETE /_aws/
Lists, or clears, the SMS messages sent through SNS, grouped by phone number.
| Query | Type | Default | Meaning |
|---|---|---|---|
phoneNumber | string | all | Only this number. Write + as %2B. |
accountId | string | all | Only this account. |
region | string | all | Only this region. |
curl "localhost:7644/_aws/sns/sms-messages?phoneNumber=%2B15555550123"{"sms_messages":{"+15555550123":[{"Timestamp":"2026-10-13T18:14:04.69832Z","MessageId":"95dd1863-35ab-4dbb-a2ed-a70009bd536d","AccountId":"000000000000","Region":"us-east-1","Protocol":"sms","Destination":"+15555550123","Message":"code 1"}]}}DELETE removes the messages that match the filters and answers 204.
List or clear push messages
GET /_aws/ and DELETE /_aws/
The same as SMS messages, for push messages. Filter with endpointArn instead of phoneNumber, and with accountId and region.
curl localhost:7644/_aws/sns/platform-endpoint-messages{"platform_endpoint_messages":{}}List Cognito codes
GET /_aws/
Lists the confirmation and verification codes Cognito "sent".
| Query | Type | Default | Meaning |
|---|---|---|---|
pool | string | all | Only this user pool id. |
username | string | all | Only this user name or destination address. |
curl localhost:7644/_aws/cognito/codes[{"pool":"us-east-1_ak5Yfk9FS","username":"u@example.com","destination":"u@example.com","code":"961860","type":"SignUp","timestamp":"2026-10-13T23:44:05.547334+05:30"}]LocalStack compatibility
Get LocalStack health
GET /_localstack/
LocalStack's health endpoint. It lists every enabled service as running. The keys of services are pogi's service ids (pogi services lists them).
curl localhost:7644/_localstack/health{"edition":"community","services":{"accessanalyzer":"running","account":"running","acm":"running", …},"version":"pogi-0.1.0"}Get LocalStack info
GET /_localstack/
LocalStack's info endpoint.
curl localhost:7644/_localstack/info{"edition":"community","is_docker":false,"is_license_activated":false,"machine_id":"pogi","server_time_utc":"2026-10-13T18:11:51Z","session_id":"pogi","system":"darwin","uptime":15,"version":"pogi-0.1.0"}Get init hook status
GET /_localstack/ and GET /_localstack/
Returns the state of the init hooks. {stage} is boot, start, ready or shutdown. Without a stage, the answer covers all four.
curl localhost:7644/_localstack/init/ready{"completed":true,"scripts":[{"stage":"READY","name":"10-seed.sh","state":"SUCCESSFUL","output":"make_bucket: from-init\n"}]}With no hooks, scripts is null for a stage, and [] for the whole list:
{"completed":{"BOOT":true,"READY":true,"SHUTDOWN":false,"START":true},"scripts":[]}Other
Get a GKE kubeconfig
GET /_gcp/
Returns a kubeconfig for a Google Kubernetes Engine cluster that pogi runs. pogi kubeconfig gke calls it.
curl localhost:7644/_gcp/gke/kubeconfig/pogi/us-central1/dev- With no such cluster, the answer is
404withno cluster projects/.pogi/ locations/ us-central1/ clusters/ dev
MCP server
/_pogi/mcp
The MCP server, over Streamable HTTP.
The rest of /_pogi/ is the web console. Its other paths are pages and form posts for the console and may change between releases. Use the endpoints above from scripts.