Appearance
API Reference
NextEpoch exposes a small set of stable integration surfaces for automation. Portal-internal APIs can change as the product evolves; use the documented interfaces below for scripts and external systems.
Service Endpoints
Copy service endpoints from the portal before wiring automation. Endpoint hostnames can differ by environment, region, and organization policy.
| Surface | Where to find it | Purpose |
|---|---|---|
| Identity | Settings > Organization > Credentials | OAuth tokens, service credentials, and organization identity APIs. |
| Registry | Apps > Catalog > Push image | Docker Registry V2-compatible image push and pull. |
| S3 Gateway | Storage > Object Storage | S3-compatible object storage endpoint. |
Authentication
Use OAuth client credentials for server-to-server calls.
bash
IDENTITY_URL="https://<identity-endpoint>"
curl -X POST "$IDENTITY_URL/oauth/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=$CLIENT_ID" \
-d "client_secret=$CLIENT_SECRET" \
-d "scope=organization:read"The response contains an access token. Send it in the Authorization header:
http
Authorization: Bearer <access-token>Create and revoke client credentials from Credentials & Webhooks.
Permissions
When you create a credential, select the smallest permission set needed for the automation task. Available permissions are shown in the credential dialog and are constrained by organization membership, service policy, and project visibility.
Docker Registry
The registry implements Docker Registry V2 behavior for organization images.
Image naming:
text
{registry-domain}/orgs/{org-slug}/{app-slug}:{tag}Example:
bash
REGISTRY_DOMAIN="<registry-domain>"
docker login "$REGISTRY_DOMAIN"
docker tag my-app:latest "$REGISTRY_DOMAIN/orgs/my-org/my-app:v1.0.0"
docker push "$REGISTRY_DOMAIN/orgs/my-org/my-app:v1.0.0"See Docker Registry for details.
S3-Compatible Storage
Provisioned object storage is available through the S3 endpoint.
bash
S3_ENDPOINT="https://<s3-endpoint>"
aws s3 --endpoint-url "$S3_ENDPOINT" lsEach provisioned app appears as a bucket at the shared endpoint. See Provisioning Storage for examples.
Webhooks
Incoming webhooks accept HTTP POST requests at the generated webhook URL.
Use webhooks for automation that sends events into your workspace. Keep webhook URLs secret and rotate them if they are exposed.
Audit Logs
Your applications can write audit events into your organization's audit trail — the same trail shown under Audit Logs — and query it back. Application events are server-marked origin: "app" alongside the platform's own events. Events are retained for 365 days, then expire automatically.
Base URL: the audit endpoint shown in the portal (e.g. https://audit.<platform-domain>).
Credentials. Writing requires a service credential or managed identity with the audit:write scope (audit:write also grants read). Agent credentials can read the trail but never write to it. The tenant is always derived from the credential — the API never accepts an organization id from the caller.
Write events
bash
curl -X POST "$AUDIT_URL/api/v1/audit/events" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"events": [{
"id": "550e8400-e29b-41d4-a716-446655440000",
"action": "invoice.exported",
"actor_id": "user_123",
"target_type": "invoice", "target_id": "inv_42",
"source_service": "billing-portal",
"metadata": {"format": "pdf"}
}]}'
# → 202 {"accepted": 1, "duplicates": 0}| Rule | Value |
|---|---|
| Batch size | ≤ 100 events per request |
| Rate limit | 300 requests/min, burst 60, per credential (429 + Retry-After) |
id | Optional UUID idempotency key — resending the same id is counted in duplicates, never stored twice. Generate it when the event happens, then retries are safe. |
timestamp | Optional RFC3339, must be within now − 30 days … now + 5 minutes (default: now) |
metadata | Arbitrary JSON ≤ 16 KB |
| Server-stamped | origin, received_at, client_id, and the organization — client values are ignored or rejected |
One invalid event rejects its whole batch with 400 and a reason; nothing from that batch is stored.
Query the trail
bash
curl "$AUDIT_URL/api/v1/audit/logs?origin=app&action_prefix=invoice.&limit=50" \
-H "Authorization: Bearer $TOKEN"Filters: action, action_prefix, actor_id, actor_type, target_type, target_id, source_service, success, origin (app | platform), from, to.
Two pagination modes (limit ≤ 100 in both):
- Offset:
?page=2&limit=50→{events, total, page, limit}. - Cursor (preferred for walking the full set):
?cursor=for the first page, then feed each response'snext_cursorback until it is absent →{events, limit, next_cursor}. Cursors are opaque — echo them, never construct them.
Returned events include the server-stamped origin, received_at, and client_id (which credential wrote the event).
Error Handling
| Status | Meaning |
|---|---|
400 | Invalid request body, path, or parameter. |
401 | Missing or invalid token. |
403 | Token is valid but lacks scope, role, organization, or project access. |
404 | Resource does not exist or is intentionally hidden by access control. |
409 | Conflict, such as duplicate slug or concurrent update. |
429 | Rate limit exceeded. |
5xx | Platform or upstream service error. Retry only if the operation is safe. |
Troubleshooting
| Symptom | What to check |
|---|---|
| Token request fails | Confirm client ID, client secret, grant type, and scopes. |
| API returns 403 | Check credential permissions and organization role. For project resources, check project membership. |
| Registry push returns denied | Confirm image name, registry login, and push access. |
| S3 client cannot connect | Confirm endpoint URL, access key, secret key, and bucket name. |
| Automation suddenly fails | Check Audit Logs for credential revocation or role changes. |