Skill: adamdurst/openclaw-essesseff (version 1.0.2)

--- name: openclaw-essesseff description: Interact with the essesseff DevOps platform — call the essesseff Public API (templates, organizations, apps, deployments, images, image lifecycle, environments, retention policies, packages) and automate app creation and Argo CD setup using the essesseff onboarding utility. Use when the user wants to create essesseff apps, manage deployments, promote images through the DEV→QA→STAGING→PROD lifecycle, configure Argo CD environments, manage retention policies, or run the essesseff-onboard.sh script. version: 1.0.0 metadata: openclaw: emoji: "🦞" homepage: https://github.com/essesseff/essesseff-onboarding-utility primaryEnv: ESSESSEFF_API_KEY requires: bins: - curl - bash - git - jq - kubectl env: - ESSESSEFF_API_KEY - ESSESSEFF_ACCOUNT_SLUG - GITHUB_ORG - APP_NAME - GITHUB_TOKEN - ARGOCD_MACHINE_USER - ARGOCD_MACHINE_EMAIL - GITHUB_ORG_ADMIN_PAT - TEMPLATE_NAME - TEMPLATE_IS_GLOBAL - K8S_NAMESPACE --- # essesseff Skill This skill covers two complementary ways to work with the essesseff DevOps platform: 1. **essesseff Public API** — direct HTTP calls for managing templates, organizations, apps, images, deployments, environments, packages, and retention policies. 2. **essesseff Onboarding Utility** — shell scripts that automate app creation and Argo CD deployment setup. ## Quick Reference **Base URL:** `https://www.essesseff.com/api/v1` (use `www` to avoid 307 redirects) **Authentication:** All requests require `X-[REDACTED_SECRET]` header. **Rate limit:** 3 requests per 10 seconds. Headers: `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`. **Path structure:** - Global (no account needed): `/api/v1/global/...` - Account-specific: `/api/v1/accounts/{account_slug}/...` — API key must belong to the `account_slug` in the path or a `403` is returned. ## API Reference Files For full endpoint details, request/response examples, and query parameters, see: | Reference | Contents | |---|---| | `references/api-overview.md` | Auth, base URL, rate limiting, error codes | | `references/api-templates.md` | Global templates, account-specific templates | | `references/api-organizations.md` | List and detail GitHub orgs for an account | | `references/api-apps.md` | Create, list, get, update apps; list deployments | | `references/api-images.md` | List images, get image by tag | | `references/api-images.md` | Image lifecycle: get state, transition state | | `references/api-environments.md` | Get environment; set Argo CD URL; DEV→QA→STAGING→PROD lifecycle actions | | `references/api-packages.md` | Get GitHub API payloads for expired package deletion | | `references/api-retention-policies.md` | List and update retention policies | ## API Endpoint Map ### Global | Method | Path | Purpose | |---|---|---| | GET | `/global/templates` | List global templates (optional `?language=go\|python\|node\|java\|rust\|php`) | | GET | `/global/templates/{template_name}` | Get global template details | ### Account-Specific (all require matching API key) | Method | Path | Purpose | |---|---|---| | GET | `/accounts/{account_slug}/templates` | List account templates | | GET | `/accounts/{account_slug}/templates/{template_name}` | Get account template details | | GET | `/accounts/{account_slug}/organizations` | List orgs for account | | GET | `/accounts/{account_slug}/organizations/{org_login}` | Get org detail + app list | | GET | `/accounts/{account_slug}/organizations/{org_login}/apps` | List apps | | POST | `/accounts/{account_slug}/organizations/{org_login}/apps?app_name={name}` | Create app | | GET | `/accounts/{account_slug}/organizations/{org_login}/apps/{app_name}` | Get app detail | | PATCH | `/accounts/{account_slug}/organizations/{org_login}/apps/{app_name}` | Update app | | GET | `.../apps/{app_name}/deployments` | List deployments | | GET | `.../apps/{app_name}/images` | List images | | GET | `.../apps/{app_name}/images/{image_tag}` | Get image by tag | | GET | `.../apps/{app_name}/images/{image_tag}/lifecycle` | Get image lifecycle state | | POST | `.../apps/{app_name}/images/{image_tag}/lifecycle` | Transition image lifecycle state | | GET | `.../apps/{app_name}/environments/{env}` | Get current env deployment | | POST | `.../apps/{app_name}/environments/{env}/set-argocd-application-url` | Set/clear Argo CD URL | | POST | `.../apps/{app_name}/environments/DEV/declare-rc` | Mark DEV image as RC | | POST | `.../apps/{app_name}/environments/QA/accept-rc` | Accept RC → deploy to QA | | POST | `.../apps/{app_name}/environments/QA/reject-rc` | Reject RC | | POST | `.../apps/{app_name}/environments/QA/declare-stable` | Mark QA image as STABLE | | POST | `.../apps/{app_name}/environments/QA/declare-rejected` | Mark QA image as REJECTED | | POST | `.../apps/{app_name}/environments/STAGING/deploy-stable` | Deploy STABLE to STAGING | | POST | `.../apps/{app_name}/environments/PROD/deploy-stable` | Deploy STABLE to PROD (no OTP) | | GET | `.../apps/{app_name}/notifications-secret` | Get notifications-secret.yaml for Argo CD | | GET | `.../apps/{app_name}/packages/delete-packages` | Get expired package deletion payloads | | GET | `.../apps/{app_name}/retention-policies` | List retention policies (filter by `?state=`) | | PATCH | `.../apps/{app_name}/retention-policies?state={state}` | Create or update a retention policy for a lifecycle state | ## Image Lifecycle State Machine Images progress through states in this order: ``` BUILD → DEV → RC → QA → STABLE → STAGING → PROD ↑ ↓ ↓ REJECTED ``` Key transitions via API: - `DEV/declare-rc` — promotes current DEV image to RC (no body) - `QA/accept-rc` — body: `{"image_tag": "v1.2.3"}` → sets QA, deploys to QA - `QA/reject-rc` — body: `{"image_tag": "v1.2.3"}` → sets REJECTED - `QA/declare-stable` — no body → sets STABLE on current QA image - `QA/declare-rejected` — no body → sets REJECTED on current QA image - `STAGING/deploy-stable` — body: `{"image_tag": "v1.2.3"}` → deploys to STAGING - `PROD/deploy-stable` — body: `{"image_tag": "v1.2.3", "deployment_note": "CR#123"}` → deploys to PROD (no OTP required via API) Alternatively, use `POST .../images/{image_tag}/lifecycle` with body `{"state": "QA"}` for direct lifecycle transitions. ## Onboarding Utility Reference For shell-script-based automation (no API calls required), see: | Reference | Contents | |---|---| | `references/onboarding-utility.md` | Full guide: setup, commands, how it works | | `references/prerequisites.md` | System binaries, PATs, K8s/Argo CD prereqs | | `references/non-subscriber-mode.md` | Clone/replace/push workflow without a subscription | The utility (`essesseff-onboard.sh`) accepts: - `--list-templates` — list available templates - `--create-app` — create all 9 repos (via API for subscribers, clone/replace/push for non-subscribers) - `--setup-argocd dev,qa,staging,prod` — configure Argo CD for each environment - `--non-essesseff-subscriber-mode` — no essesseff API required - `--config-file .essesseff` — path to config file - `--verbose` — debug output ## Common Errors | Code | Meaning | |---|---| | 400 | Invalid request parameters | | 401 | Invalid or missing API key | | 403 | API key does not match the `account_slug` in the path | | 404 | Resource not found | | 429 | Rate limit exceeded — wait and retry | | 500 | Server error |

path: bundled-global-templates.json
content: name: essesseff-hello-world-fastapi-template
language: python
description: essesseff Hello World FastAPI app template
template_org_login: essesseff-hello-world-fastapi-template
source_template_repo: hello-world
is_global_template: yes
replacement_string: hello-world

name: essesseff-hello-world-flask-template
language: python
description: essesseff Hello World Python Flask template
template_org_login: essesseff-hello-world-flask-template
source_template_repo: hello-world
is_global_template: yes
replacement_string: hello-world

name: essesseff-hello-world-go-template
language: go
description: essesseff Hello World Go template
template_org_login: essesseff-hello-world-go-template
source_template_repo: hello-world
is_global_template: yes
replacement_string: hello-world

name: essesseff-hello-world-nodejs-template
language: node
description: essesseff Hello World Node.js template
template_org_login: essesseff-hello-world-nodejs-template
source_template_repo: hello-world
is_global_template: yes
replacement_string: hello-world

name: essesseff-hello-world-php-template
language: php
description: essesseff Hello World PHP template
template_org_login: essesseff-hello-world-php-template
source_template_repo: hello-world
is_global_template: yes
replacement_string: hello-world

name: essesseff-helloworld-springboot-templat
language: java
description: essesseff Hello World Java Spring Boot template
template_org_login: essesseff-helloworld-springboot-templat
source_template_repo: helloworld
is_global_template: yes
replacement_string: helloworld

path: README.md
content: # openclaw-essesseff

> **OpenClaw skill** — install via [ClawHub](https://clawhub.ai)

A comprehensive OpenClaw AgentSkill for the [essesseff](https://www.essesseff.com) DevOps platform. Covers both direct API interaction and shell-script-based app onboarding.

## What This Skill Covers

### essesseff Public API
Full reference for all public API endpoints:
- **Templates** — list and retrieve global and account-specific app templates
- **Organizations** — list and inspect GitHub orgs for your account
- **Apps** — create, list, get, and update essesseff apps
- **Deployments** — query deployment history by environment and status
- **Images** — list container images, get by tag
- **Image Lifecycle** — get current state, drive DEV→RC→QA→STABLE→STAGING→PROD transitions
- **Environments** — get current env deployment, set Argo CD URLs, drive promotion pipeline
- **Packages** — get GitHub API payloads for expired image package deletion
- **Retention Policies** — list and update per-lifecycle-state retention days (BUILD, DEV, RC, QA, STABLE, STAGING, PROD, REJECTED, EXPIRED, etc.)

### essesseff Onboarding Utility
Shell-script automation for:
- Listing available templates
- Creating all 9 essesseff repositories (via API for subscribers, or clone/replace/push for non-subscribers)
- Configuring Argo CD for dev, qa, staging, and/or prod environments

## Install

```bash
npx clawhub@latest install openclaw-essesseff
```

Or via the ClawHub CLI:

```bash
clawhub install openclaw-essesseff
```

## References

| File | Contents |
|---|---|
| `references/api-overview.md` | Auth, base URL, rate limiting, error codes |
| `references/api-templates.md` | Global and account-specific template endpoints |
| `references/api-organizations.md` | Organization list and detail |
| `references/api-apps.md` | App CRUD, deployments, notifications secret |
| `references/api-images.md` | Image list, get by tag, lifecycle get/transition |
| `references/api-environments.md` | Environment status, Argo CD URL, full promotion pipeline |
| `references/api-packages.md` | Expired package deletion payloads |
| `references/api-retention-policies.md` | Retention policy list and update |
| `references/onboarding-utility.md` | Full onboarding utility guide and CLI reference |
| `references/prerequisites.md` | System binaries, PATs, K8s/Argo CD prereqs |
| `references/non-subscriber-mode.md` | Clone/replace/push workflow for non-subscribers |

## Prerequisites

- `curl` — for API calls
- `ESSESSEFF_API_KEY` — from your essesseff team account settings
- For the onboarding utility: `bash` 4.0+, `git`, `jq`; `kubectl` for Argo CD setup

## Quick Start — API

```bash
export ESSESSEFF_API_KEY=ess_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
export ACCOUNT=my-team
export ORG=my-apps-org
BASE=https://www.essesseff.com/api/v1

# List global templates
curl -H "X-[REDACTED_SECRET]" "$BASE/global/templates"

# Create an app
curl -X POST "$BASE/accounts/$ACCOUNT/organizations/$ORG/apps?app_name=my-app" \
  -H "X-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "My Go app",
    "programming_language": "go",
    "template": {
      "template_org_login": "essesseff-hello-world-go-template",
      "source_template_repo": "hello-world",
      "is_global_template": true,
      "replacement_string": "hello-world"
    }
  }'

# Check QA environment
curl -H "X-[REDACTED_SECRET]" \
  "$BASE/accounts/$ACCOUNT/organizations/$ORG/apps/my-app/environments/QA"

# Deploy STABLE image to PROD
curl -X POST \
  "$BASE/accounts/$ACCOUNT/organizations/$ORG/apps/my-app/environments/PROD/deploy-stable" \
  -H "X-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{"image_tag": "v1.2.3", "deployment_note": "CR#12345"}'
```

## Quick Start — Onboarding Utility

```bash
git clone https://github.com/essesseff/essesseff-onboarding-utility.git
cd essesseff-onboarding-utility
chmod +x essesseff-onboard.sh
cp essesseff-example.txt .essesseff
# fill in .essesseff, then:
./essesseff-onboard.sh --create-app --setup-argocd dev,qa,staging,prod --config-file .essesseff
```

## Security

- Never commit `.essesseff` files — they contain API keys and tokens.
- Delete `notifications-secret.yaml` after applying it to your cluster.
- API keys are only issuable to account owners and DevOps Engineers.

## License

MIT


path: essesseff-example.txt
content: # essesseff API Configuration (required when NOT using --non-essesseff-subscriber-mode)
ESSESSEFF_API_KEY=your-essesseff-api-key-here
# ESSESSEFF_API_BASE_URL=https://essesseff.com/api/v1  # Optional - defaults to https://essesseff.com/api/v1
ESSESSEFF_ACCOUNT_SLUG=my-team

# GitHub Org Admin PAT (required ONLY for --create-app when using --non-essesseff-subscriber-mode)
# Used to create repos in GITHUB_ORG and push cloned-and-replaced content (including .github/workflows).
# Classic PAT: grant "repo" and "workflow" scopes. Fine-grained: Contents + Metadata + Workflows read/write.
# Do not confuse with GITHUB_TOKEN (Argo CD machine user).
# GITHUB_ORG_ADMIN_PAT=[REDACTED_SECRET]

# GitHub Machine User Credentials (required for Argo CD setup: --setup-argocd)
# See: https://www.essesseff.com/docs/deployment/github-argocd-machine-user-setup#step-0:-tldr---quick-setup-for-essesseff-onboarding-utility
ARGOCD_MACHINE_USER="your-argocd-machine-username"
GITHUB_TOKEN="[REDACTED_SECRET]"
ARGOCD_MACHINE_EMAIL="[REDACTED_SECRET]"

# Organization/App Config (required)
GITHUB_ORG="my-org"
APP_NAME="my-app"

# Template Configuration (required for --create-app)
# For subscriber mode: TEMPLATE_IS_GLOBAL required. For --non-essesseff-subscriber-mode: use template name = GitHub org.
# All current possible TEMPLATE_NAME values (global templates):
#   TEMPLATE_NAME="essesseff-hello-world-fastapi-template"    # Python FastAPI
#   TEMPLATE_NAME="essesseff-hello-world-flask-template"      # Python Flask
#   TEMPLATE_NAME="essesseff-hello-world-go-template"         # Go
#   TEMPLATE_NAME="essesseff-hello-world-nodejs-template"     # Node.js
#   TEMPLATE_NAME="essesseff-hello-world-php-template"        # PHP
#   TEMPLATE_NAME="essesseff-helloworld-springboot-templat"   # Java Spring Boot
TEMPLATE_NAME="essesseff-hello-world-go-template"
TEMPLATE_IS_GLOBAL=true

# App Configuration (optional for --create-app)
APP_DESCRIPTION="My new essesseff app"
REPOSITORY_VISIBILITY="private"

# K8S_NAMESPACE (optional) - Kubernetes namespace for {{K8S_NAMESPACE}} in templates; if unset, GITHUB_ORG is used (must be valid K8s namespace)
# K8S_NAMESPACE="my-k8s-namespace"

# Argo CD Instance URL (optional, for --setup-argocd only; subscriber mode only)
# When set, the utility will register each environment's Argo CD application URL with essesseff
# (e.g. https://argocd.example.com/applications/argocd/my-app-dev)
# ARGOCD_INSTANCE_URL="https://argocd.example.com"


path: gitignore.txt
content: # essesseff config files contain secrets — never commit them
.essesseff
.essesseff.*
!essesseff-example.txt

# Cloned template repos (created during --non-essesseff-subscriber-mode)
# These land in the current working directory during app creation.
# Uncomment the lines below if you want git to ignore them automatically,
# or just delete the folders after verifying the push succeeded.
# *-config-dev/
# *-config-qa/
# *-config-staging/
# *-config-prod/
# *-argocd-dev/
# *-argocd-qa/
# *-argocd-staging/
# *-argocd-prod/

# OS / editor noise
.DS_Store
Thumbs.db
.idea/
.vscode/
*.swp
*.swo


path: references/api-apps.md
content: # Apps API

Source: https://www.essesseff.com/docs/api/apps

Manage essesseff apps, deployments, images, and retention policies.

---

## GET /accounts/{account_slug}/organizations/{organization_login}/apps

List essesseff apps

```
GET /api/v1/accounts/{account_slug}/organizations/{organization_login}/apps
```

### Path Parameters

#### account_slug (required)

The team account slug (name) associated with the API key. The API key must belong to this account.

#### organization_login (required)

GitHub organization login to list apps for (matched case-insensitively)

### Description

Lists essesseff apps for a team account. Supports filtering by organization and app name. Returns app details including repository URLs, template information, and creation timestamps.

### Query Parameters

#### app_name (optional)

Filter by app name (exact match). For single app operations, use the full path endpoint instead.

#### limit (optional)

Maximum number of results to return (default: 50)

#### offset (optional)

Number of results to skip for pagination (default: 0)

### Request Example

```
curl -X GET \
  "https://www.essesseff.com/api/v1/accounts/my-team/organizations/my-apps-org/apps" \
  -H "X-[REDACTED_SECRET]"
```

With optional app_name filter:

```
curl -X GET \
  "https://www.essesseff.com/api/v1/accounts/my-team/organizations/my-apps-org/apps?app_name=my-app" \
  -H "X-[REDACTED_SECRET]"
```

### Response Example

```json
{
  "success": true,
  "data": [
    {
      "app_name": "my-app",
      "organization_login": "my-apps-org",
      "description": "My essesseff app",
      "programming_language": "go",
      "repository_visibility": "private",
      "template": {
        "name": "essesseff-hello-world-go-template",
        "language": "go",
        "is_global_template": true
      },
      "created_at": "2025-01-01T00:00:00Z",
      "repository_urls": {
        "source_repo": "https://github.com/my-apps-org/my-app",
        "config_dev_repo": "https://github.com/my-apps-org/my-app-config-dev",
        "config_qa_repo": "https://github.com/my-apps-org/my-app-config-qa",
        "config_staging_repo": "https://github.com/my-apps-org/my-app-config-staging",
        "config_prod_repo": "https://github.com/my-apps-org/my-app-config-prod",
        "argocd_dev_repo": "https://github.com/my-apps-org/my-app-argocd-dev",
        "argocd_qa_repo": "https://github.com/my-apps-org/my-app-argocd-qa",
        "argocd_staging_repo": "https://github.com/my-apps-org/my-app-argocd-staging",
        "argocd_prod_repo": "https://github.com/my-apps-org/my-app-argocd-prod"
      }
    }
  ],
  "pagination": {
    "total": 1,
    "limit": 50,
    "offset": 0,
    "has_more": false
  }
}
```

---

## POST /accounts/{account_slug}/organizations/{organization_login}/apps

Create a new essesseff app

```
POST /api/v1/accounts/{account_slug}/organizations/{organization_login}/apps?app_name={app_name}
```

### Path Parameters

#### account_slug (required)

The team account slug (name) associated with the API key. The API key must belong to this account.

#### organization_login (required)

GitHub organization login where the app will be created (e.g., "my-apps-org")

### Query Parameters

#### app_name (required)

Name of the essesseff app to create (must be URL-compliant: lowercase letters, numbers, and hyphens only)

### Description

Creates a new essesseff app with the specified configuration. The app creation process includes creating 9 GitHub repositories (1 source + 4 config + 4 Argo CD), setting up webhooks, assigning teams, and configuring retention policies.

### Request Body

Note: `account_slug`, `organization_login`, and `app_name` are now provided in the path and query parameters, not in the request body.

#### template (required)

Template configuration object:

- `template_org_login` - Template organization login (e.g., "essesseff-hello-world-go-template")
- `source_template_repo` - Source template repository name (e.g., "hello-world")
- `is_global_template` - Boolean indicating if this is a global template
- `replacement_string` - String to replace in templates (always "hello-world" for global templates)

#### description (optional)

Description of the app

#### programming_language (optional)

Programming language (e.g., "go", "java", "node", "python")

#### repository_visibility (optional)

Repository visibility: "private" or "public" (default: "private")

#### k8s_namespace (optional)

Kubernetes namespace used to replace "{{K8S_NAMESPACE}}" in templates. If omitted, the target GitHub organization (`organization_login`) is used as the namespace. When provided (or when using the org as fallback), the value must be a valid Kubernetes namespace: at most 63 characters, lowercase letters, numbers, and hyphens only, and must start and end with a letter or number. Invalid values return 400 with a descriptive error.

### Request Examples

Below are examples for each available global template:

#### Java Spring Boot Template

```
curl -X POST \
  "https://www.essesseff.com/api/v1/accounts/my-team/organizations/my-apps-org/apps?app_name=my-java-app" \
  -H "X-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "My Java Spring Boot application",
    "programming_language": "java",
    "template": {
      "template_org_login": "essesseff-helloworld-springboot-templat",
      "source_template_repo": "helloworld",
      "is_global_template": true,
      "replacement_string": "helloworld"
    },
    "repository_visibility": "private"
  }'
```

#### Go Template

```
curl -X POST \
  "https://www.essesseff.com/api/v1/accounts/my-team/organizations/my-apps-org/apps?app_name=my-go-app" \
  -H "X-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "My Go application",
    "programming_language": "go",
    "template": {
      "template_org_login": "essesseff-hello-world-go-template",
      "source_template_repo": "hello-world",
      "is_global_template": true,
      "replacement_string": "hello-world"
    },
    "repository_visibility": "private"
  }'
```

#### Node.js Template

```
curl -X POST \
  "https://www.essesseff.com/api/v1/accounts/my-team/organizations/my-apps-org/apps?app_name=my-nodejs-app" \
  -H "X-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "My Node.js application",
    "programming_language": "node",
    "template": {
      "template_org_login": "essesseff-hello-world-nodejs-template",
      "source_template_repo": "hello-world",
      "is_global_template": true,
      "replacement_string": "hello-world"
    },
    "repository_visibility": "private"
  }'
```

#### Python Flask Template

```
curl -X POST \
  "https://www.essesseff.com/api/v1/accounts/my-team/organizations/my-apps-org/apps?app_name=my-python-app" \
  -H "X-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "My Python Flask application",
    "programming_language": "python",
    "template": {
      "template_org_login": "essesseff-hello-world-flask-template",
      "source_template_repo": "hello-world",
      "is_global_template": true,
      "replacement_string": "hello-world"
    },
    "repository_visibility": "private"
  }'
```

### Response Example

```json
{
  "success": true,
  "data": {
    "account_slug": "my-team",
    "app_name": "my-app",
    "organization_login": "my-apps-org",
    "description": "My essesseff app",
    "programming_language": "go",
    "resultant_repos": {
      "source_repo": "my-app",
      "config_dev_repo": "my-app-config-dev",
      "config_qa_repo": "my-app-config-qa",
      "config_staging_repo": "my-app-config-staging",
      "config_prod_repo": "my-app-config-prod",
      "argocd_dev_repo": "my-app-argocd-dev",
      "argocd_qa_repo": "my-app-argocd-qa",
      "argocd_staging_repo": "my-app-argocd-staging",
      "argocd_prod_repo": "my-app-argocd-prod",
      "template_org_login": "essesseff-hello-world-go-template",
      "is_global_template": true,
      "replacement_string": "hello-world"
    },
    "repository_visibility": "private"
  }
}
```

### Template Notes

For global templates, the `replacement_string` is always `"hello-world"` (or `"helloworld"` for Java Spring Boot template). The system will automatically replace `"hello-world"` and/or `"helloworld"` with the specified `app_name` when cloning repository content from the templates.

---

## GET /accounts/{account_slug}/organizations/{organization_login}/apps/{app_name}

Get app details

```
GET /api/v1/accounts/{account_slug}/organizations/{organization_login}/apps/{app_name}
```

### Description

Gets app details including all repository IDs and URLs. Returns 404 if app doesn't exist.

### Path Parameters

#### account_slug (required)

The team account slug (name) associated with the API key

#### organization_login (required)

GitHub organization login where the app exists

#### app_name (required)

Name of the essesseff app

### Request Example

```
curl -X GET \
  "https://www.essesseff.com/api/v1/accounts/my-team/organizations/my-apps-org/apps/my-app" \
  -H "X-[REDACTED_SECRET]"
```

### Response Example

```json
{
  "success": true,
  "data": {
    "app_name": "my-app",
    "organization_login": "my-apps-org",
    "description": "My essesseff app",
    "programming_language": "go",
    "repository_visibility": "private",
    "template": {
      "name": "essesseff-hello-world-go-template",
      "language": "go",
      "is_global_template": true
    },
    "created_at": "2025-01-01T00:00:00Z",
    "updated_at": "2025-01-01T00:00:00Z",
    "repository_urls": {
      "source_repo": "https://github.com/my-apps-org/my-app",
      "config_dev_repo": "https://github.com/my-apps-org/my-app-config-dev",
      "config_qa_repo": "https://github.com/my-apps-org/my-app-config-qa",
      "config_staging_repo": "https://github.com/my-apps-org/my-app-config-staging",
      "config_prod_repo": "https://github.com/my-apps-org/my-app-config-prod",
      "argocd_dev_repo": "https://github.com/my-apps-org/my-app-argocd-dev",
      "argocd_qa_repo": "https://github.com/my-apps-org/my-app-argocd-qa",
      "argocd_staging_repo": "https://github.com/my-apps-org/my-app-argocd-staging",
      "argocd_prod_repo": "https://github.com/my-apps-org/my-app-argocd-prod"
    },
    "repository_ids": {
      "source_repo": 12345678,
      "config_dev_repo": 12345679,
      "config_qa_repo": 12345680,
      "config_staging_repo": 12345681,
      "config_prod_repo": 12345682,
      "argocd_dev_repo": 12345683,
      "argocd_qa_repo": 12345684,
      "argocd_staging_repo": 12345685,
      "argocd_prod_repo": 12345686
    }
  }
}
```

---

## PATCH /accounts/{account_slug}/organizations/{organization_login}/apps/{app_name}

Update an existing essesseff app

```
PATCH /api/v1/accounts/{account_slug}/organizations/{organization_login}/apps/{app_name}
```

### Description

Updates an existing essesseff app. Currently supports updating description and repository visibility (private/public). When repository visibility is updated, all repositories associated with the app are updated in both the database and GitHub.

### Path Parameters

#### account_slug (required)

The team account slug (name) associated with the API key

#### organization_login (required)

GitHub organization login where the app exists

#### app_name (required)

Name of the essesseff app to update

### Request Body

#### description (optional)

Updated app description

#### repository_visibility (optional)

Repository visibility: "private" or "public"

At least one of description or repository_visibility must be provided.

### Request Example

```
curl -X PATCH \
  "https://www.essesseff.com/api/v1/accounts/my-team/organizations/my-apps-org/apps/my-app" \
  -H "X-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "Updated description",
    "repository_visibility": "public"
  }'
```

### Response Example

```json
{
  "success": true,
  "data": {
    "app_name": "my-app",
    "description": "Updated description",
    "repository_visibility": "public",
    "updated_at": "2025-01-02T00:00:00Z"
  }
}
```

---

## GET /accounts/{account_slug}/organizations/{organization_login}/apps/{app_name}/deployments

List deployments for an app

```
GET /api/v1/accounts/{account_slug}/organizations/{organization_login}/apps/{app_name}/deployments
```

### Description

Lists deployments for a specific essesseff app. Supports filtering by environment (dev, qa, staging, prod) and status (pending, in_progress, succeeded, failed). Returns deployment details including image tags, GitHub commit information, and deployment timestamps.

### Path Parameters

#### app_name (required)

Name of the essesseff app

### Query Parameters

#### account_slug (required)

The team account slug (name) associated with the API key

#### organization_login (required)

GitHub organization login where the app exists

#### environment (optional)

Filter by environment: dev, qa, staging, prod

#### status (optional)

Filter by status: pending, in_progress, succeeded, failed

#### limit (optional)

Maximum number of results (default: 50, max: 1000)

#### offset (optional)

Number of results to skip for pagination (default: 0)

### Request Example

```
curl -X GET \
  "https://www.essesseff.com/api/v1/accounts/my-team/organizations/my-apps-org/apps/my-app/deployments?environment=prod&status=succeeded" \
  -H "X-[REDACTED_SECRET]"
```

### Response Example

```json
{
  "success": true,
  "data": [
    {
      "app_name": "my-app",
      "environment": "prod",
      "status": "succeeded",
      "image_tag": "v1.2.3",
      "github_sha": "abc123def456",
      "github_ref": "refs/heads/main",
      "deployed_at": "2025-01-01T12:00:00Z",
      "completed_at": "2025-01-01T12:05:00Z",
      "metadata": {
        "github_repository": "my-apps-org/my-app",
        "github_workflow_run_id": 12345678,
        "deployment_method": "manual_promote",
        "deployment_conclusion": "success",
        "health_status": "Healthy"
      }
    }
  ],
  "pagination": {
    "total": 10,
    "limit": 50,
    "offset": 0,
    "has_more": false
  }
}
```

---

## GET /accounts/{account_slug}/organizations/{organization_login}/apps/{app_name}/notifications-secret

Get notifications-secret.yaml for Argo CD setup

```
GET /api/v1/accounts/{account_slug}/organizations/{organization_login}/apps/{app_name}/notifications-secret
```

### Description

Retrieves the notifications-secret.yaml file content for Argo CD setup. Returns YAML content with `Content-Type: application/x-yaml`. This file contains Argo CD Notifications Event Processor API keys and environment-specific app secrets.

**Note:** Secrets are automatically issued from the database when this file is generated if they don't already exist.

### Path Parameters

#### account_slug (required)

The team account slug (name) associated with the API key

#### organization_login (required)

GitHub organization login where the app exists

#### app_name (required)

Name of the essesseff app

### Request Example

```
curl -X GET \
  "https://www.essesseff.com/api/v1/accounts/my-team/organizations/my-apps-org/apps/my-app/notifications-secret" \
  -H "X-[REDACTED_SECRET]" \
  -o notifications-secret.yaml
```

### Response

Returns YAML content with `Content-Type: application/x-yaml`:

```yaml
# notifications-secret.yaml

# Store Argo CD Notifications Event Processor API key and environment-specific app secrets
# ***DELETE THIS FILE AFTER APPLYING - DO NOT COMMIT SECRETS TO GITHUB***

apiVersion: v1
kind: Secret
metadata:
  name: argocd-notifications-secret
  namespace: argocd
type: Opaque
stringData:
  argocd-webhook-url: "https://api.essesseff.com/api/v1/argocd/webhook"
  aws-api-gateway-key-my-apps-org: "ess_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
  app-secret-12345678: "abc123def456..."
  app-secret-12345679: "xyz789uvw012..."
  app-secret-12345680: "mno345pqr678..."
  app-secret-12345681: "ghi901jkl234..."
```

The response includes secrets for all environments (dev, qa, staging, prod) that have config repositories. Secret keys are environment-specific: `app-secret-{config-env-repository-id}`


path: references/api-environments.md
content: # Environments API

Source: https://www.essesseff.com/docs/api/apps

Get environment status and drive the image promotion pipeline through DEV → QA → STAGING → PROD.

All paths begin with: `/api/v1/accounts/{account_slug}/organizations/{organization_login}/apps/{app_name}/environments`

Valid `{env}` values (case-sensitive in path): `DEV`, `QA`, `STAGING`, `PROD`

---

## GET .../environments/{env}

Get current deployment for an environment

```
GET /api/v1/accounts/{account_slug}/organizations/{organization_login}/apps/{app_name}/environments/{env}
```

### Path Parameters

`env` must be one of: DEV, QA, STAGING, PROD.

### Description

Returns the image currently deployed to the given environment. Response includes account_slug, organization, app, environment, image_name, image_tag, state_timestamp, and argocd_application_url (optional URL to the Argo CD application for this environment, if set in app settings). If no deployment exists, image_name, image_tag, and state_timestamp are null.

### Request Example

```
curl -X GET \
  "https://www.essesseff.com/api/v1/accounts/my-team/organizations/my-apps-org/apps/my-app/environments/QA" \
  -H "X-[REDACTED_SECRET]"
```

### Response Example (200, with deployment)

```json
{
  "account_slug": "my-team",
  "organization": "my-apps-org",
  "app": "my-app",
  "environment": "QA",
  "image_name": "my-app",
  "image_tag": "v1.2.3",
  "state_timestamp": "2025-09-30T11:00:00Z",
  "argocd_application_url": "https://argocd.example.com/applications/argocd/my-app-qa"
}
```

### Response Example (200, no deployment)

When no image is deployed to the environment:

```json
{
  "account_slug": "my-team",
  "organization": "my-apps-org",
  "app": "my-app",
  "environment": "QA",
  "image_name": null,
  "image_tag": null,
  "state_timestamp": null,
  "argocd_application_url": null
}
```

---

## POST .../environments/{env}/set-argocd-application-url

Set Argo CD application URL for an environment

```
POST /api/v1/accounts/{account_slug}/organizations/{organization_login}/apps/{app_name}/environments/{env}/set-argocd-application-url
```

### Path Parameters

`env` must be one of: DEV, QA, STAGING, PROD.

### Description

Sets the optional Argo CD application URL for the given environment. The URL is stored in app settings and shown in the essesseff UI (deployment cards, app settings). The URL is validated and normalized (trailing slash removed). Send `null` or empty to clear. Returns 204 on success.

### Request Body

`url` (optional): string or null. Full URL to the Argo CD application for this environment (e.g. `https://argocd.example.com/applications/argocd/my-app-qa`). Max 1000 characters. Omit or set to null to clear.

### Request Example

```
curl -X POST \
  "https://www.essesseff.com/api/v1/accounts/my-team/organizations/my-apps-org/apps/my-app/environments/QA/set-argocd-application-url" \
  -H "X-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://argocd.example.com/applications/argocd/my-app-qa"}'
```

### Response

Returns 204 No Content on success. Returns 400 for invalid env or invalid URL format.

---

## POST .../environments/DEV/declare-rc

Set current DEV deployment image lifecycle to RC

```
POST /api/v1/accounts/{account_slug}/organizations/{organization_login}/apps/{app_name}/environments/DEV/declare-rc
```

No body. Sets the current DEV deployment image's lifecycle state to RC.

### Request Example

```
curl -X POST \
  "https://www.essesseff.com/api/v1/accounts/my-team/organizations/my-apps-org/apps/my-app/environments/DEV/declare-rc" \
  -H "X-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{}'
```

### Response Example (200)

```json
{
  "account_slug": "my-team",
  "organization": "my-apps-org",
  "app": "my-app",
  "environment": "DEV",
  "image_name": "my-app",
  "image_tag": "v1.2.3",
  "state": "RC",
  "state_timestamp": "2025-09-30T12:00:00Z"
}
```

---

## POST .../environments/QA/accept-rc

Accept release candidate and deploy to QA

```
POST /api/v1/accounts/{account_slug}/organizations/{organization_login}/apps/{app_name}/environments/QA/accept-rc
```

Body: `{"image_tag": "v1.2.3"}`. Sets image lifecycle to QA, promotes config_qa, and creates a deployment record.

### Request Example

```
curl -X POST \
  "https://www.essesseff.com/api/v1/accounts/my-team/organizations/my-apps-org/apps/my-app/environments/QA/accept-rc" \
  -H "X-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{"image_tag": "v1.2.3"}'
```

### Response Example (200)

```json
{
  "account_slug": "my-team",
  "organization": "my-apps-org",
  "app": "my-app",
  "environment": "QA",
  "image_name": "my-app",
  "image_tag": "v1.2.3",
  "state": "QA",
  "state_timestamp": "2025-09-30T12:00:00Z"
}
```

---

## POST .../environments/QA/reject-rc

Reject a release candidate

```
POST /api/v1/accounts/{account_slug}/organizations/{organization_login}/apps/{app_name}/environments/QA/reject-rc
```

Body: `image_tag`. Sets image lifecycle to REJECTED.

### Request Example

```
curl -X POST \
  "https://www.essesseff.com/api/v1/accounts/my-team/organizations/my-apps-org/apps/my-app/environments/QA/reject-rc" \
  -H "X-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{"image_tag": "v1.2.3"}'
```

### Response Example (200)

```json
{
  "account_slug": "my-team",
  "organization": "my-apps-org",
  "app": "my-app",
  "environment": "QA",
  "image_name": "my-app",
  "image_tag": "v1.2.3",
  "state": "REJECTED",
  "state_timestamp": "2025-09-30T12:00:00Z"
}
```

---

## POST .../environments/QA/declare-stable

Set current QA deployment image to STABLE

```
POST /api/v1/accounts/{account_slug}/organizations/{organization_login}/apps/{app_name}/environments/QA/declare-stable
```

No body. Sets the current QA deployment image's lifecycle state to STABLE.

### Request Example

```
curl -X POST \
  "https://www.essesseff.com/api/v1/accounts/my-team/organizations/my-apps-org/apps/my-app/environments/QA/declare-stable" \
  -H "X-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{}'
```

### Response Example (200)

```json
{
  "account_slug": "my-team",
  "organization": "my-apps-org",
  "app": "my-app",
  "environment": "QA",
  "image_name": "my-app",
  "image_tag": "v1.2.3",
  "state": "STABLE",
  "state_timestamp": "2025-09-30T12:00:00Z"
}
```

---

## POST .../environments/QA/declare-rejected

Set current QA deployment image to REJECTED

```
POST /api/v1/accounts/{account_slug}/organizations/{organization_login}/apps/{app_name}/environments/QA/declare-rejected
```

No body. Sets the current QA deployment image's lifecycle state to REJECTED.

### Request Example

```
curl -X POST \
  "https://www.essesseff.com/api/v1/accounts/my-team/organizations/my-apps-org/apps/my-app/environments/QA/declare-rejected" \
  -H "X-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{}'
```

### Response Example (200)

```json
{
  "account_slug": "my-team",
  "organization": "my-apps-org",
  "app": "my-app",
  "environment": "QA",
  "image_name": "my-app",
  "image_tag": "v1.2.3",
  "state": "REJECTED",
  "state_timestamp": "2025-09-30T12:00:00Z"
}
```

---

## POST .../environments/STAGING/deploy-stable

Deploy STABLE image to STAGING

```
POST /api/v1/accounts/{account_slug}/organizations/{organization_login}/apps/{app_name}/environments/STAGING/deploy-stable
```

Body: `image_tag`. Deploys the given STABLE image to STAGING (lifecycle STAGING, config_staging promotion, deployment record).

### Request Example

```
curl -X POST \
  "https://www.essesseff.com/api/v1/accounts/my-team/organizations/my-apps-org/apps/my-app/environments/STAGING/deploy-stable" \
  -H "X-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{"image_tag": "v1.2.3"}'
```

### Response Example (200)

```json
{
  "account_slug": "my-team",
  "organization": "my-apps-org",
  "app": "my-app",
  "environment": "STAGING",
  "image_name": "my-app",
  "image_tag": "v1.2.3",
  "state": "STAGING",
  "state_timestamp": "2025-09-30T12:00:00Z"
}
```

---

## POST .../environments/PROD/deploy-stable

Deploy STABLE image to PROD (no OTP required via API)

```
POST /api/v1/accounts/{account_slug}/organizations/{organization_login}/apps/{app_name}/environments/PROD/deploy-stable
```

Body: `image_tag`, optional `deployment_note`. Same as STAGING but for PROD. No OTP required when using the API.

### Request Example

```
curl -X POST \
  "https://www.essesseff.com/api/v1/accounts/my-team/organizations/my-apps-org/apps/my-app/environments/PROD/deploy-stable" \
  -H "X-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{"image_tag": "v1.2.3", "deployment_note": "CR#12345"}'
```

### Response Example (200)

```json
{
  "account_slug": "my-team",
  "organization": "my-apps-org",
  "app": "my-app",
  "environment": "PROD",
  "image_name": "my-app",
  "image_tag": "v1.2.3",
  "state": "PROD",
  "state_timestamp": "2025-09-30T12:00:00Z",
  "deployment_note": "CR#12345"
}
```

Response includes `deployment_note` (the value sent in the request body, or `null` if omitted).


path: references/api-overview.md
content: # essesseff Public API — Overview

Source: https://www.essesseff.com/docs/api

## Overview

The essesseff Public API provides programmatic access to essesseff platform features. All API requests require authentication via API keys and are subject to rate limiting.

## Base URL

```
https://www.essesseff.com/api/v1
```

Use the `www` host to avoid 307 redirects.

## Authentication

All API requests must include an API key in the `X-API-Key` header:

```
X-[REDACTED_SECRET]
```

API keys can be generated and managed in your team account settings (`/home/[account]/settings`). API keys are only issuable to account owners and DevOps Engineers.

## API Structure

The essesseff API uses a hierarchical path structure to express context explicitly:

- **Global resources**: `/api/v1/global/...` (system-level resources, not account-specific)
- **Account-specific resources**: `/api/v1/accounts/{account_slug}/...` (requires account_slug in path)

For account-specific endpoints, the API key **must** belong to the account_slug specified in the path. If the API key does not match the account_slug, a `403 Forbidden` error is returned.

## Rate Limiting

API requests are rate-limited to 3 requests per 10 seconds.

Rate limit information is included in response headers:

```
X-RateLimit-Limit: 3
X-RateLimit-Remaining: 2
X-RateLimit-Reset: 1234567890
```

## Error Handling

Errors are returned in JSON format with appropriate HTTP status codes:

```json
{
  "error": "Error message describing what went wrong",
  "message": "Additional details about the error"
}
```

Common error codes:

- `400 Bad Request` - Invalid request parameters
- `401 Unauthorized` - Invalid or missing API key
- `403 Forbidden` - API key does not belong to the specified account_slug
- `404 Not Found` - Resource not found
- `429 Too Many Requests` - Rate limit exceeded
- `500 Internal Server Error` - Server error

## API Endpoints

Available essesseff public API endpoints organized by context hierarchy.

### Global Resources

System-level resources available to all authenticated users (no account_slug required).

#### GET /global/templates

List available global essesseff app templates. Supports optional filtering by programming language.

#### GET /global/templates/{template_name}

Get complete details for a specific global template (all fields needed for app creation).

### Account-Specific Resources

All account-specific endpoints require `account_slug` in the path. The API key must belong to the specified account_slug.

#### Templates

##### GET /accounts/{account_slug}/templates

List team-account-specific templates for the specified account.

##### GET /accounts/{account_slug}/templates/{template_name}

Get complete details for a team-account-specific template.

#### Organizations

##### GET /accounts/{account_slug}/organizations

List GitHub organizations associated with a team account.

##### GET /accounts/{account_slug}/organizations/{organization_login}

Retrieve detailed information about a specific GitHub organization with app list.

#### Apps

##### POST /accounts/{account_slug}/organizations/{organization_login}/apps

Create a new essesseff app. Requires `app_name` as a query parameter.

##### GET /accounts/{account_slug}/organizations/{organization_login}/apps

List essesseff apps for an organization. Supports optional filtering by app_name.

##### GET /accounts/{account_slug}/organizations/{organization_login}/apps/{app_name}

Get app details including all repository IDs and URLs.

##### PATCH /accounts/{account_slug}/organizations/{organization_login}/apps/{app_name}

Update an existing essesseff app (description, repository_visibility).

#### App Resources

##### GET .../apps/{app_name}/deployments

List deployments for a specific essesseff app. Supports filtering by environment and status.

##### GET .../apps/{app_name}/images

List container images for a specific essesseff app. Supports filtering by repository, tag, and status.

##### GET .../apps/{app_name}/images/{image_tag}

Get detailed information about a specific container image by tag.

##### GET .../apps/.../images/{image_tag}/lifecycle

Get image lifecycle state (optional history).

##### POST .../apps/.../images/{image_tag}/lifecycle

Update image lifecycle state; can trigger environment deployment.

##### GET .../apps/.../environments/{env}

Get current deployment for an environment (DEV, QA, STAGING, PROD). Response includes argocd_application_url when set.

##### POST .../environments/{env}/set-argocd-application-url

Set or clear Argo CD application URL for an environment (body: url or null). Returns 204.

##### POST .../environments/DEV/declare-rc

Set current DEV image lifecycle to RC (no body).

##### POST .../environments/QA/accept-rc

Accept RC and deploy to QA (body: image_tag).

##### POST .../environments/QA/reject-rc

Reject RC (body: image_tag).

##### POST .../environments/QA/declare-stable

Set current QA image to STABLE (no body).

##### POST .../environments/QA/declare-rejected

Set current QA image to REJECTED (no body).

##### POST .../environments/STAGING/deploy-stable

Deploy STABLE image to STAGING (body: image_tag).

##### POST .../environments/PROD/deploy-stable

Deploy STABLE image to PROD (body: image_tag, optional deployment_note; no OTP).

##### GET .../apps/{app_name}/retention-policies

List retention policies for a specific essesseff app.

##### PATCH .../apps/{app_name}/retention-policies

Update an existing retention policy for a specific app and lifecycle state.

##### GET .../apps/{app_name}/notifications-secret

Retrieve the notifications-secret.yaml file content for Argo CD setup. Returns YAML content.

#### Other Endpoints

##### GET .../apps/{app_name}/packages/delete-packages

Retrieve GitHub API payloads for deleting package versions that correspond to expired essesseff images.

## Getting Started

1. Generate an API key in your team account settings (`/home/[account]/settings`)
2. Include the API key in the `X-API-Key` header of all requests
3. Review the individual endpoint documentation for request/response formats
4. Implement proper error handling and rate limit management in your client code


path: references/onboarding-utility.md
content: # essesseff Onboarding Utility

Automates essesseff app creation and Argo CD deployment setup using shell scripts.

## Overview

- **For subscribers**: Creates all 9 repos via the essesseff Public API (~5 minutes).
- **For non-subscribers** (`--non-essesseff-subscriber-mode`): Clones template repos, replaces strings, creates GitHub repos, and pushes (~1 minute).
- **Argo CD setup**: Configures Argo CD for dev, qa, staging, and/or prod environments.

## Setup

```bash
git clone https://github.com/essesseff/essesseff-onboarding-utility.git
cd essesseff-onboarding-utility
chmod +x essesseff-onboard.sh
# Optional wizard:
chmod +x essesseff-onboard-wizard.sh

cp essesseff-example.txt .essesseff
# Edit .essesseff with your values (or run essesseff-onboard-wizard.sh)
```

## Configuration Variables

### Required for essesseff Subscribers Only
- `ESSESSEFF_API_KEY` — API key from team account settings
- `ESSESSEFF_ACCOUNT_SLUG` — team account slug

### Required for All Operations
- `GITHUB_ORG` — target GitHub organization login
- `APP_NAME` — app name (lowercase letters, numbers, hyphens; no leading/trailing hyphens)

### For `--create-app`
- `TEMPLATE_NAME` — template name (e.g. `essesseff-hello-world-go-template`)
- `TEMPLATE_IS_GLOBAL` — `true` for global, `false` for account-specific

### For `--create-app` with `--non-essesseff-subscriber-mode`
- `GITHUB_ORG_ADMIN_PAT` — GitHub PAT with `repo` + `workflow` scopes (classic) or Contents/Metadata/Workflows R/W (fine-grained)

### For `--setup-argocd`
- `ARGOCD_MACHINE_USER` — Argo CD machine user username
- `GITHUB_TOKEN` — machine user PAT (`repo` + `read:packages`) — not the same as `GITHUB_ORG_ADMIN_PAT`
- `ARGOCD_MACHINE_EMAIL` — machine user email

### Optional
- `APP_DESCRIPTION` — app description
- `REPOSITORY_VISIBILITY` — `private` (default) or `public`
- `K8S_NAMESPACE` — override the destination K8s namespace (defaults to `GITHUB_ORG`; must be DNS compliant and < 63 characters)

### Optional — essesseff Subscribers Only
- `ARGOCD_INSTANCE_URL` — base URL of your Argo CD instance (e.g. `https://argocd.example.com`); when set, each environment's Argo CD app URL is registered with essesseff
- `ESSESSEFF_API_BASE_URL` — override essesseff API base URL (defaults to `https://essesseff.com/api/v1`)

## Commands

### List templates
```bash
./essesseff-onboard.sh --list-templates --config-file .essesseff
./essesseff-onboard.sh --list-templates --language go --config-file .essesseff
```

### Create app only
```bash
./essesseff-onboard.sh --create-app --config-file .essesseff
# Non-subscriber mode:
./essesseff-onboard.sh --create-app --non-essesseff-subscriber-mode --config-file .essesseff
```

### Create app + configure Argo CD
```bash
./essesseff-onboard.sh \
  --create-app \
  --setup-argocd dev,qa,staging,prod \
  --config-file .essesseff
```

### Configure Argo CD only (app already exists)
```bash
./essesseff-onboard.sh --setup-argocd dev,qa --config-file .essesseff
```

### Verbose / debug
```bash
./essesseff-onboard.sh --create-app --verbose --config-file .essesseff
```

## All CLI Flags

| Flag | Description |
|---|---|
| `--list-templates` | List available templates |
| `--language LANG` | Filter by language: go, python, node, java |
| `--create-app` | Create new essesseff app (all 9 repos) |
| `--setup-argocd ENVS` | Comma-separated environments: dev,qa,staging,prod |
| `--non-essesseff-subscriber-mode` | Clone/replace/push workflow, no API |
| `--config-file FILE` | Config file path (default: `.essesseff`) |
| `--verbose` | Enable debug output |
| `-h, --help` | Show help |

## How It Works

### App Creation
1. Validates app name (GitHub naming rules).
2. Checks app doesn't already exist.
3. Fetches template details.
4. Creates all 9 repos (API for subscribers; clone → replace → push for non-subscribers).

**String replacement (non-subscriber mode) — literal, case-sensitive:**
- `template_org_login` (e.g. `essesseff-hello-world-go-template`) → `GITHUB_ORG`
- `replacement_string` from template (e.g. `hello-world`) → `APP_NAME`

### Argo CD Setup
For each environment:
1. (Subscribers) Downloads `notifications-secret.yaml`.
2. Clones the argocd-env repo (`{app-name}-argocd-{env}`).
3. Creates `.env` file with required variables.
4. (Subscribers) Copies `notifications-secret.yaml` to repo.
5. Runs `setup-argocd.sh`.

**Variables written to `.env` files:**
- `ARGOCD_MACHINE_USER`, `GITHUB_TOKEN`, `ARGOCD_MACHINE_EMAIL`
- `GITHUB_ORG`, `APP_NAME`, `ENVIRONMENT`
- `K8S_NAMESPACE` (if set)

essesseff API credentials (`ESSESSEFF_API_KEY`, `ESSESSEFF_API_BASE_URL`, `ESSESSEFF_ACCOUNT_SLUG`) and app creation variables (`APP_DESCRIPTION`, `REPOSITORY_VISIBILITY`, `TEMPLATE_NAME`, `TEMPLATE_IS_GLOBAL`) are NOT copied to `.env` files as they are not needed by `setup-argocd.sh`.

## Troubleshooting

| Problem | Solution |
|---|---|
| `kubectl is not properly configured` | Configure kubectl for the target cluster — hard prerequisite |
| `App 'my-app' already exists` | Choose a different `APP_NAME` or delete the existing app |
| Template clone fails | Template repos are public. Check the git error (usually "Repository not found" or transient network issue). Retry. |
| Commit or push fails to argocd-env repo | Ensure `git config user.name` and `user.email` are set, and git profile has push access |
| Strings not replaced | Replacement is case-sensitive. Check `replacement_string` in `bundled-global-templates.json` matches what's in the template repo exactly. |
| K8s namespace rejected | `K8S_NAMESPACE` must be DNS compliant and < 63 chars. If unset, `GITHUB_ORG` is used — ensure it also meets these constraints. |
| Rate limit warning | Utility auto-retries. Wait for it. |

## Security

- Never commit `.essesseff` files — they contain secrets.
- `gitignore.txt` excludes `.essesseff` automatically (rename to `.gitignore` in your repo).
- Delete `notifications-secret.yaml` after applying it to your cluster.


path: references/api-retention-policies.md
content: # Retention Policies API

Source: https://www.essesseff.com/docs/api/apps#retention-policies

---

## GET /accounts/{account_slug}/organizations/{organization_login}/apps/{app_name}/retention-policies

List retention policies for an app

```
GET /api/v1/accounts/{account_slug}/organizations/{organization_login}/apps/{app_name}/retention-policies
```

### Description

Lists lifecycle-state retention policies for a specific essesseff app. Retention policies are defined per image lifecycle state (BUILD, DEV, RC, QA, STABLE, STAGING, PROD, REJECTED, EXPIRED, etc.). For each state, the endpoint flattens account-wide defaults and app-specific overrides into a single app-scoped policy (app-level overrides take precedence over account-level defaults).

### Path Parameters

#### account_slug (required)

The team account slug (name) associated with the API key

#### organization_login (required)

GitHub organization login where the app exists

#### app_name (required)

Name of the essesseff app

### Query Parameters

#### state (optional)

Filter by lifecycle state (or comma-separated list of states). Valid values include: BUILD, DEV, RC, QA, STABLE, STAGING, PROD, REJECTED, EXPIRED, etc. If omitted, all lifecycle states for the app are returned.

### Request Example

```
curl -X GET \
  "https://www.essesseff.com/api/v1/accounts/my-team/organizations/my-apps-org/apps/my-app/retention-policies?state=PROD" \
  -H "X-[REDACTED_SECRET]"
```

### Response Example

```json
{
  "success": true,
  "data": [
    {
      "app_name": "my-app",
      "state": "PROD",
      "retention_days": 30,
      "scope": "app",
      "created_at": "2025-01-01T00:00:00Z",
      "updated_at": "2025-01-01T00:00:00Z"
    },
    {
      "app_name": "my-app",
      "state": "BUILD",
      "retention_days": 3,
      "scope": "account",
      "created_at": "2025-01-01T00:00:00Z",
      "updated_at": "2025-01-01T00:00:00Z"
    }
  ]
}
```

---

## PATCH /accounts/{account_slug}/organizations/{organization_login}/apps/{app_name}/retention-policies

Update a retention policy

```
PATCH /api/v1/accounts/{account_slug}/organizations/{organization_login}/apps/{app_name}/retention-policies?state={state}
```

### Description

Creates or updates a lifecycle-state retention policy for a specific app. Allows modifying retention_days for a single lifecycle state (e.g. PROD, QA, BUILD, etc.). Retention policies updated via this endpoint are app-specific and override any account-wide defaults for the same state.

### Path Parameters

#### account_slug (required)

The team account slug (name) associated with the API key

#### organization_login (required)

GitHub organization login where the app exists

#### app_name (required)

Name of the essesseff app

### Query Parameters

#### state (required)

Lifecycle state to update (e.g. BUILD, DEV, RC, QA, STABLE, STAGING, PROD, REJECTED, EXPIRED).

### Request Body

#### retention_days (required)

Number of days to retain images in this lifecycle state (non-negative integer)

### Request Example

```
curl -X PATCH \
  "https://www.essesseff.com/api/v1/accounts/my-team/organizations/my-apps-org/apps/my-app/retention-policies?state=PROD" \
  -H "X-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{
    "retention_days": 60
  }'
```

### Response Example

```json
{
  "success": true,
  "data": {
    "app_name": "my-app",
    "state": "PROD",
    "retention_days": 60,
    "updated_at": "2025-01-02T00:00:00Z"
  }
}
```


path: references/prerequisites.md
content: # Prerequisites Reference

This document expands on the prerequisites listed in `SKILL.md`.

## System Binaries

| Binary | Min Version | Purpose |
|---|---|---|
| `bash` | 4.0 | Script runtime |
| `curl` | any | API calls |
| `git` | any | Repo cloning and pushing; a git profile with commit/push access to the argocd-env repos is also required for `--setup-argocd` |
| `jq` | any | JSON parsing |
| `kubectl` | any | Argo CD setup only |

Install on macOS via Homebrew:
```bash
brew install bash curl git jq kubectl
```

Install on Ubuntu/Debian:
```bash
sudo apt-get update && sudo apt-get install -y curl git jq
# kubectl: https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/
```

## GitHub PATs

### GitHub Org Admin PAT (non-subscriber `--create-app` only)

Used to create the 9 repos and push content (including `.github/workflows`).

**Classic PAT** — scopes needed:
- `repo` — create repos, push code
- `workflow` — create/update `.github/workflows` files

**Fine-grained PAT** — permissions needed (org-level or all repos):
- Contents: Read and write
- Metadata: Read
- Workflows: Read and write
- Token user must have permission to create repositories in the org.

> **Do not confuse** this with the Argo CD machine user token (`GITHUB_TOKEN`).

### Argo CD Machine User PAT (`GITHUB_TOKEN`)

A separate GitHub account dedicated to Argo CD. It needs:
- `repo` scope — pull config repos
- `read:packages` scope — pull container images from GHCR

Setup guide: https://www.essesseff.com/docs/deployment/github-argocd-machine-user-setup

## Kubernetes + Argo CD

- Any K8s cluster works, including a single-VM `k3s` setup.
- Argo CD must be installed. The `setup-argocd-cluster.sh` script in this repo provides an easy way to do this.
- `kubectl` must be configured (`~/.kube/config` or `KUBECONFIG` env var) and pointing at the correct cluster for each environment **before** running `--setup-argocd`.
- The destination K8s namespace defaults to the `GITHUB_ORG` string. If your org name isn't DNS compliant or is 63+ characters, set `K8S_NAMESPACE` in `.essesseff` to a valid override.

## essesseff API Key (subscribers only)

Available from your essesseff team settings page. Must belong to the account in `ESSESSEFF_ACCOUNT_SLUG`.


path: references/api-images.md
content: # Images API

Source: https://www.essesseff.com/docs/api/apps

List container images and manage image lifecycle state.

All paths begin with: `/api/v1/accounts/{account_slug}/organizations/{organization_login}/apps/{app_name}`

---

## GET .../images

List container images for an app

```
GET /api/v1/accounts/{account_slug}/organizations/{organization_login}/apps/{app_name}/images
```

### Description

Lists container images for a specific essesseff app. Supports filtering by repository name, image tag, and status (active, expired, all). Returns image metadata including GitHub package version IDs.

### Path Parameters

#### app_name (required)

Name of the essesseff app

### Query Parameters

#### account_slug (required)

The team account slug (name) associated with the API key

#### organization_login (required)

GitHub organization login where the app exists

#### repository_name (optional)

Filter by GitHub repository name

#### image_tag (optional)

Filter by image tag

#### status (optional)

Filter by status: active, expired, all (default: all)

#### limit (optional)

Maximum number of results (default: 100, max: 1000)

#### offset (optional)

Number of results to skip for pagination (default: 0)

### Request Example

```
curl -X GET \
  "https://www.essesseff.com/api/v1/accounts/my-team/organizations/my-apps-org/apps/my-app/images?status=active" \
  -H "X-[REDACTED_SECRET]"
```

### Response Example

```json
{
  "success": true,
  "data": [
    {
      "app_name": "my-app",
      "repository_name": "my-app",
      "image_name": "my-app",
      "image_tag": "v1.2.3",
      "status": "active",
      "github_package_version_id": 12345678,
      "created_at": "2025-01-01T00:00:00Z",
      "expired_at": null,
      "metadata": {
        "github_organization": "my-apps-org",
        "package_type": "container"
      }
    }
  ],
  "pagination": {
    "total": 50,
    "limit": 100,
    "offset": 0,
    "has_more": false
  }
}
```

---

## GET .../images/{image_tag}

Get image details by tag

```
GET /api/v1/accounts/{account_slug}/organizations/{organization_login}/apps/{app_name}/images/{image_tag}
```

### Description

Retrieves detailed information about a specific container image by tag. If multiple repositories have the same image tag, use the repository_name query parameter to disambiguate.

### Path Parameters

#### account_slug (required)

The team account slug (name) associated with the API key

#### organization_login (required)

GitHub organization login where the app exists

#### app_name (required)

Name of the essesseff app

#### image_tag (required)

Image tag (e.g., "v1.2.3")

### Query Parameters

#### repository_name (optional)

GitHub repository name (required if multiple repos have same tag)

### Request Example

```
curl -X GET \
  "https://www.essesseff.com/api/v1/accounts/my-team/organizations/my-apps-org/apps/my-app/images/v1.2.3" \
  -H "X-[REDACTED_SECRET]"
```

### Response Example

```json
{
  "success": true,
  "data": {
    "app_name": "my-app",
    "repository_name": "my-app",
    "image_name": "my-app",
    "image_tag": "v1.2.3",
    "status": "active",
    "github_package_version_id": 12345678,
    "created_at": "2025-01-01T00:00:00Z",
    "expired_at": null,
    "metadata": {
      "github_organization": "my-apps-org",
      "package_type": "container",
      "github_package_url": "https://github.com/my-apps-org/my-app/pkgs/container/my-app"
    }
  }
}
```

---

## GET .../images/{image_tag}/lifecycle

Get image lifecycle state; optional history

```
GET /api/v1/accounts/{account_slug}/organizations/{organization_login}/apps/{app_name}/images/{image_tag}/lifecycle
```

### Description

Returns current lifecycle state and timestamp for the image. Query `history=true` to include state history (no UUIDs). Response includes account_slug, organization, app, image_name, image_tag, current_state, state_timestamp.

### Query Parameters

#### history (optional)

Set to `true` or `1` to include state history in the response.

### Request Example

```
curl -X GET \
  "https://www.essesseff.com/api/v1/accounts/my-team/organizations/my-apps-org/apps/my-app/images/v1.2.3/lifecycle?history=true" \
  -H "X-[REDACTED_SECRET]"
```

### Response Example (200, no history)

```json
{
  "account_slug": "my-team",
  "organization": "my-apps-org",
  "app": "my-app",
  "image_name": "my-app",
  "image_tag": "v1.2.3",
  "current_state": "RC",
  "state_timestamp": "2025-09-30T12:00:00Z"
}
```

### Response Example (200, with history=true)

```json
{
  "account_slug": "my-team",
  "organization": "my-apps-org",
  "app": "my-app",
  "image_name": "my-app",
  "image_tag": "v1.2.3",
  "current_state": "RC",
  "state_timestamp": "2025-09-30T12:00:00Z",
  "history": [
    { "state": "BUILD", "state_timestamp": "2025-09-30T10:00:00Z", "is_active": false },
    { "state": "DEV",   "state_timestamp": "2025-09-30T11:00:00Z", "is_active": false },
    { "state": "RC",    "state_timestamp": "2025-09-30T12:00:00Z", "is_active": true }
  ]
}
```

---

## POST .../images/{image_tag}/lifecycle

Update image lifecycle state; can trigger environment deployment

```
POST /api/v1/accounts/{account_slug}/organizations/{organization_login}/apps/{app_name}/images/{image_tag}/lifecycle
```

### Description

Transition the image to a new lifecycle state. Body: `state` (required); optional `deployment_note` when state is PROD. Only allowed transitions (per lifecycle table) are accepted; same-state or backwards transitions return 400. When state is DEV, QA, STAGING, or PROD, the API also performs the corresponding environment deployment (config repo promotion and deployment record). PROD via API does not require OTP.

### Request Example

```
curl -X POST \
  "https://www.essesseff.com/api/v1/accounts/my-team/organizations/my-apps-org/apps/my-app/images/v1.2.3/lifecycle" \
  -H "X-[REDACTED_SECRET]" \
  -H "Content-Type: application/json" \
  -d '{"state": "QA"}'
```

### Response Example (200)

```json
{
  "account_slug": "my-team",
  "organization": "my-apps-org",
  "app": "my-app",
  "image_name": "my-app",
  "image_tag": "v1.2.3",
  "state": "QA",
  "state_timestamp": "2025-09-30T12:00:00Z"
}
```


path: references/api-packages.md
content: # Packages API

Source: https://www.essesseff.com/docs/api/packages/delete-packages

---

## GET /accounts/{account_slug}/organizations/{organization_login}/apps/{app_name}/packages/delete-packages

Retrieve GitHub API payloads for deleting expired package versions

```
GET /api/v1/accounts/{account_slug}/organizations/{organization_login}/apps/{app_name}/packages/delete-packages
```

### Description

Returns GitHub API payloads for deleting package versions that correspond to expired essesseff images. The function validates that all uniquely tagged images associated with a particular GitHub package version are expired before returning the package version for deletion.

**Important:** This endpoint only returns deletion payloads. You must execute the deletion using a GitHub Personal Access Token (PAT) with appropriate permissions, as GitHub Apps cannot reliably delete package versions via the API.

### Path Parameters

#### account_slug (required)

The team account slug (name) associated with the API key

#### organization_login (required)

GitHub organization login (e.g., "my-apps-org")

#### app_name (required)

essesseff app name. The repository name is automatically derived from the app's source repository.

### Query Parameters

#### assume_deleted (required)

Boolean (true/false). If true, marks all returned package version IDs as assume_to_be_deleted in the database, preventing duplicate payloads on subsequent requests. If false, does not mark them.

#### limit (optional)

Maximum number of results to return (default: 100)

#### offset (optional)

Number of results to skip for pagination (default: 0)

### Request Example

```
curl -X GET \
  "https://www.essesseff.com/api/v1/accounts/my-team/organizations/my-apps-org/apps/my-app/packages/delete-packages?assume_deleted=true" \
  -H "X-[REDACTED_SECRET]"
```

### Response Example

```json
{
  "success": true,
  "data": [
    {
      "package_version_id": 12345678,
      "organization_login": "my-apps-org",
      "repository_name": "my-app",
      "package_name": "my-app",
      "github_api_endpoint": "DELETE /repos/{owner}/{repo}/packages/{package_type}/{package_name}/versions/{package_version_id}",
      "github_api_params": {
        "owner": "my-apps-org",
        "repo": "my-app",
        "package_type": "container",
        "package_name": "my-app",
        "package_version_id": 12345678
      },
      "github_api_url": "https://api.github.com/repos/my-apps-org/my-app/packages/container/my-app/versions/12345678",
      "metadata": {
        "expired_tags": [
          {
            "image_tag": "v1.0.0",
            "expired_at": "2025-01-01T00:00:00Z"
          },
          {
            "image_tag": "v1.0.1",
            "expired_at": "2025-01-02T00:00:00Z"
          }
        ],
        "all_tags_expired": true
      }
    }
  ],
  "pagination": {
    "total": 1,
    "limit": 100,
    "offset": 0,
    "has_more": false
  }
}
```

### Best Practices

#### When to use assume_deleted=true

Use `assume_deleted=true` when you are confident that you will execute the deletion using the returned payloads. This prevents the same package versions from being returned on subsequent requests.

#### When to use assume_deleted=false

Use `assume_deleted=false` when you want to preview what would be deleted without committing to the deletion. The same package versions will be returned on subsequent requests until you use `assume_deleted=true`.

#### Executing Deletions

To delete a package version, make a DELETE request to the `github_api_url` using a GitHub Personal Access Token (PAT) with the `delete:packages` permission:

```
curl -X DELETE \
  "https://api.github.com/repos/my-apps-org/my-app/packages/container/my-app/versions/12345678" \
  -H "Authorization: token YOUR_GITHUB_PAT"
```


path: references/non-subscriber-mode.md
content: # Non-Subscriber Mode Guide

Use `--non-essesseff-subscriber-mode` if you don't have an essesseff subscription. This mode:

- Does **not** use the essesseff API.
- Clones template repos from GitHub directly (they are public).
- Performs literal, case-sensitive string replacement on all repo contents.
- Creates new repos in your GitHub org using the GitHub API.
- Pushes the replaced content to the new repos.

## What Gets Replaced

The script performs two string replacements across all cloned file contents and filenames:

1. `template_org_login` (the template's GitHub org, e.g. `essesseff-hello-world-go-template`) → `GITHUB_ORG`
2. The template's `replacement_string` from `bundled-global-templates.json` (e.g. `hello-world`) → `APP_NAME`

Replacement is **literal and case-sensitive**. Variants like `HelloWorld`, `hello_world`, or `HELLO-WORLD` will not be replaced.

## After the Run

Cloned repos land in the current working directory. They are **not deleted** after push, so you can inspect them:

```bash
ls -d my-new-app*/
```

Check a repo to verify replacements:
```bash
grep -r "hello-world" my-new-app/ | head -20
```

If you see unexpected occurrences, the template may use naming variants not covered by the two replacement strings.

## Bundled Templates

Available templates are in `bundled-global-templates.json` in this repo. Filter by language:

```bash
./essesseff-onboard.sh --list-templates --language go --non-essesseff-subscriber-mode --config-file .essesseff
```

Languages available: `go`, `node`, `python`, `java`.


path: references/api-templates.md
content: # Templates API

Source: https://www.essesseff.com/docs/api/templates

List and retrieve essesseff app templates (global and account-specific).

---

## GET /global/templates

List global essesseff app templates

```
GET /api/v1/global/templates
```

### Description

Lists all available global essesseff app templates. Global templates are system-level templates provided by essesseff (not account-specific). No account_slug is required for global endpoints.

### Query Parameters

#### language (optional)

Filter templates by programming language: `go`, `python`, `node`, `java`, `rust`, `php`

### Request Example

```
curl -X GET \
  "https://www.essesseff.com/api/v1/global/templates" \
  -H "X-[REDACTED_SECRET]"
```

With language filter:

```
curl -X GET \
  "https://www.essesseff.com/api/v1/global/templates?language=go" \
  -H "X-[REDACTED_SECRET]"
```

### Response Example

```json
[
  {
    "name": "essesseff-hello-world-go-template",
    "language": "go",
    "description": "essesseff Hello World Go template",
    "template_org_login": "essesseff-hello-world-go-template",
    "source_template_repo": "hello-world",
    "is_global_template": true,
    "replacement_string": "hello-world"
  },
  {
    "name": "essesseff-helloworld-springboot-templat",
    "language": "java",
    "description": "essesseff Hello World Java Spring Boot template",
    "template_org_login": "essesseff-helloworld-springboot-templat",
    "source_template_repo": "helloworld",
    "is_global_template": true,
    "replacement_string": "helloworld"
  }
]
```

**Note:** For global templates, `replacement_string` is typically `"hello-world"` (Go, Python, Node.js templates), except for Java (Spring Boot) which uses `"helloworld"` (no hyphen).

---

## GET /global/templates/{template_name}

Get global template details

```
GET /api/v1/global/templates/{template_name}
```

### Description

Gets complete details for a specific global template (all fields needed for app creation).

### Path Parameters

#### template_name (required)

The unique name of the global template (e.g., "essesseff-hello-world-go-template")

### Request Example

```
curl -X GET \
  "https://www.essesseff.com/api/v1/global/templates/essesseff-hello-world-go-template" \
  -H "X-[REDACTED_SECRET]"
```

### Response Example

```json
{
  "name": "essesseff-hello-world-go-template",
  "language": "go",
  "description": "essesseff Hello World Go template",
  "template_org_login": "essesseff-hello-world-go-template",
  "source_template_repo": "hello-world",
  "is_global_template": true,
  "replacement_string": "hello-world"
}
```

---

## GET /accounts/{account_slug}/templates

List team-account-specific templates

```
GET /api/v1/accounts/{account_slug}/templates
```

### Description

Lists all team-account-specific templates for the specified account. The API key must belong to the specified account_slug.

### Path Parameters

#### account_slug (required)

The team account slug (name) associated with the API key. The API key must belong to this account.

### Query Parameters

#### language (optional)

Filter templates by programming language: `go`, `python`, `node`, `java`, `rust`, `php`

### Request Example

```
curl -X GET \
  "https://www.essesseff.com/api/v1/accounts/my-team/templates" \
  -H "X-[REDACTED_SECRET]"
```

### Response Example

```json
[
  {
    "name": "my-custom-template",
    "language": "go",
    "description": "Custom Go template for my team",
    "template_org_login": "my-org",
    "source_template_repo": "my-custom-template-repo",
    "is_global_template": false,
    "replacement_string": "hello-world"
  }
]
```

---

## GET /accounts/{account_slug}/templates/{template_name}

Get team-account-specific template details

```
GET /api/v1/accounts/{account_slug}/templates/{template_name}
```

### Description

Gets complete details for a team-account-specific template (all fields needed for app creation).

### Path Parameters

#### account_slug (required)

The team account slug (name) associated with the API key. The API key must belong to this account.

#### template_name (required)

The unique name of the team-account-specific template

### Request Example

```
curl -X GET \
  "https://www.essesseff.com/api/v1/accounts/my-team/templates/my-custom-template" \
  -H "X-[REDACTED_SECRET]"
```

### Response Example

```json
{
  "name": "my-custom-template",
  "language": "go",
  "description": "Custom Go template for my team",
  "template_org_login": "my-org",
  "source_template_repo": "my-custom-template-repo",
  "is_global_template": false,
  "replacement_string": "hello-world"
}
```


path: references/api-organizations.md
content: # Organizations API

Source: https://www.essesseff.com/docs/api/organizations

List and retrieve GitHub organizations for team accounts.

---

## GET /accounts/{account_slug}/organizations

List GitHub organizations for a team account

```
GET /api/v1/accounts/{account_slug}/organizations
```

### Description

Lists GitHub organizations associated with a team account. Returns organization details including GitHub organization IDs, creation timestamps, and app counts.

### Path Parameters

#### account_slug (required)

The team account slug (name) associated with the API key. The API key must belong to this account.

### Query Parameters

#### limit (optional)

Maximum number of results to return (default: 50, max: 1000)

#### offset (optional)

Number of results to skip for pagination (default: 0)

### Request Example

```
curl -X GET \
  "https://www.essesseff.com/api/v1/accounts/my-team/organizations" \
  -H "X-[REDACTED_SECRET]"
```

### Response Example

```json
{
  "success": true,
  "data": [
    {
      "organization_login": "my-apps-org",
      "github_organization_id": 12345678,
      "created_at": "2025-01-01T00:00:00Z",
      "app_count": 5
    }
  ],
  "pagination": {
    "total": 2,
    "limit": 50,
    "offset": 0,
    "has_more": false
  }
}
```

---

## GET /accounts/{account_slug}/organizations/{organization_login}

Retrieve detailed information about a GitHub organization

```
GET /api/v1/accounts/{account_slug}/organizations/{organization_login}
```

### Description

Retrieves detailed information about a specific GitHub organization. Returns organization details including GitHub organization ID, creation timestamp, app count, and a list of apps with names and creation timestamps.

### Path Parameters

#### account_slug (required)

The team account slug (name) associated with the API key. The API key must belong to this account.

#### organization_login (required)

GitHub organization login (e.g., "my-apps-org"; matched case-insensitively)

### Request Example

```
curl -X GET \
  "https://www.essesseff.com/api/v1/accounts/my-team/organizations/my-apps-org" \
  -H "X-[REDACTED_SECRET]"
```

### Response Example

```json
{
  "success": true,
  "data": {
    "organization_login": "my-apps-org",
    "github_organization_id": 12345678,
    "created_at": "2025-01-01T00:00:00Z",
    "app_count": 5,
    "apps": [
      {
        "app_name": "my-app",
        "created_at": "2025-01-01T00:00:00Z"
      }
    ]
  }
}
```


Security scan verdicts — ClawScan: suspicious | static analysis: suspicious | VirusTotal: stale | SkillSpector: suspicious (CRITICAL)