Metadata-Version: 2.4
Name: liveapisec
Version: 0.1.11
Summary: LiveAPISec Developer API client — push API specs, run security scans and gate your CI/CD from the command line.
Author: LiveAPISec
License: MIT
Project-URL: Homepage, https://liveapisec.com
Project-URL: Documentation, https://liveapisec.com/settings
Keywords: security,api,dast,scanning,ci,cd
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Security
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: httpx>=0.24
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: ruff>=0.5; extra == "dev"

# liveapisec — CLI/SDK for the LiveAPISec Developer API

Official, thin client for the **LiveAPISec Developer API**. Install it once,
use it in any project, script and CI/CD pipeline — no dashboard, no curl.

> **When to use this?** Instead of walking through the wizard in the dashboard,
> a developer pushes endpoints + an optional token from **their own**
> environment (CI/CD, agent, script). The token is generated on your side and
> encrypted server-side (AES-256).
> **Tip: no token = we only test what's public.**

---

## Which APIs does it work with? (not Python-only)

The `liveapisec` CLI is **written in Python** — but that is only the tool you
run. You use it to push, test and monitor APIs built in **any** language and
framework: Python, Node.js, Go, Rust, Java/Kotlin, PHP, Ruby, .NET/C#… It does
not matter how your backend is implemented, as long as it exposes HTTP(S)
endpoints.

**3 ways to get your endpoints in:**

1. **`push`** — list endpoints yourself (works for **any** HTTP API).
2. **`push --openapi-url …`** — pull an OpenAPI spec (FastAPI/DRF, Springdoc,
   NestJS Swagger, express swagger-ui, ASP.NET Swashbuckle…).
3. **`push-code`** — scan the source code; it auto-detects these
   **11 frameworks**:

| Language | Frameworks recognized by `push-code` |
|----------|---------------------------------------|
| Python   | FastAPI · Flask · Django              |
| JS/TS    | Next.js (App + Pages Router) · NestJS · Express |
| PHP      | Laravel · PHP/Slim · Lumen            |
| Java     | Spring MVC / Spring Boot (`@GetMapping`) |
| Go       | Gin · Echo · Fiber · Chi · gorilla/mux · `net/http` |
| Rust     | axum · actix-web · rocket · warp      |

**What kind of applications work?** REST/JSON APIs — microservices, monoliths,
BFFs, API gateways, third-party APIs… public or protected (jwt / bearer /
cookie / api_key / OAuth2). `push-code` reads the HTTP routes; the app behind
them can be anything.

**Integration & SDK:** the package also ships a **Python SDK**
(`from liveapisec import LiveAPISec`), and the same Developer API is a plain
**REST** API you can call from **any language** (curl, Node `fetch`, Go…) — the
CLI just wraps those endpoints. See the [SDK section](#sdk) below and the
in-browser docs at **https://liveapisec.com/docs**.

---

## Installation

### One command (Linux / macOS) — recommended

```bash
curl -fsSL https://raw.githubusercontent.com/LiveApiSec/liveapisec/main/install.sh | bash
```

The installer uses `pipx` when available, otherwise it creates an isolated
virtualenv and symlinks the command into `~/.local/bin` — no `sudo`, and it
works on PEP 668 systems (Ubuntu 24.04+) where a plain `pip install` is
blocked. After installing, open a new terminal and run `liveapisec --help`.

### From PyPI (recommended for developers with pipx/venv)

```bash
pipx install liveapisec     # or: pip install liveapisec (inside a venv)
```

### From GitHub (if you prefer building from the repository)

```bash
pip install "liveapisec @ git+https://github.com/LiveApiSec/liveapisec.git"
```

Verify:

```bash
liveapisec --help
```

Install once (e.g. in a CI image, on a dev machine, in GitHub Actions) and the
`liveapisec` command is available **in every project** on that machine.

---

## Configuration

Generate an API key once in the dashboard: **Settings → Developer API → Create API key**
(the `las_dev_...` key is shown only once — store it as a secret).

### First run (interactive)

The first time you run a command that needs the API (e.g. `push`, `scan`), the CLI
asks for your key, shows you exactly where to find it, and **saves it** to
`~/.config/liveapisec/config.json` (mode `0600`). Next runs pick it up automatically:

```
$ liveapisec push --name my-api --base-url https://api.example.com ...
No LiveAPISec API key found.
Generate one in the dashboard:  Settings → Developer API → Create API key
  https://liveapisec.com/settings
The key looks like:  las_dev_...
Tip: no key = only public endpoints can be tested.
Paste your API key: las_dev_...
✓ API key saved to /home/you/.config/liveapisec/config.json
```

### Environment variables (recommended for CI)

```bash
export LIVEAPISEC_API_KEY=las_dev_...          # required
export LIVEAPISEC_API_URL=https://liveapisec.com   # optional (default)
```

Precedence: `--api-key` / `--api-url` flags → environment variables →
saved config file.

### Manage the saved key

```bash
liveapisec config        # show where the key is stored
liveapisec config --clear  # remove the saved config file
```

---

## Commands

### Interactive mode (project + site picker)

When you run `push` / `push-code` in a terminal and **omit `--project`** (or
`--site`), the CLI shows the projects available for your API key and lets you
pick one — or create a new one. After picking a project you can pick an existing
site/URL inside it, or add a new URL:

```
$ liveapisec push --endpoint "GET /users"
No --project given. Pick a project (or create a new one):
  1) svc      (3 site(s))
  2) mobile   (1 site(s))
  3) create new project
Enter number or project name: 1
Now pick a site/URL in 'svc' (or add a new one):
  1) api-a  https://a.example.com
  2) api-b  https://b.example.com
  3) add new URL/site
Enter number: 2
→ updating existing site api-b
✓ site 65f...: api-b — 2 endpoints, auth=none
  export SITE_ID=65f...
```

In CI (no TTY) the flags are required as before — nothing changes in pipelines.

### 1. `push` — push your API (idempotent, safe in CI)

```bash
liveapisec push \
  --name my-api \
  --base-url https://api.example.com \
  --endpoint "GET /users" \
  --endpoint "POST /payments"
```

- The same `name` + `base_url` = **the same site** (update, not a duplicate) —
  you can call push in every build.
- Instead of a list of endpoints you can provide an OpenAPI spec: `--openapi-url https://api.example.com/openapi.json`.
- Optional token: `--auth-type jwt --auth-token <TOKEN>` (or `bearer`,
  `cookie --auth-cookie "session=..."`, `api_key --auth-header X-API-Key`).

#### OAuth2 Client Credentials (M2M) — recommended for CI/CD

Short-lived JWTs expire before the scan runs. Instead, register a
**Machine-to-Machine** application in your identity provider (Auth0, Okta,
Azure AD, Keycloak…) once and push the long-lived client credentials — our
scanner fetches a **fresh token at every scan**:

```bash
liveapisec push --name my-api --base-url https://api.example.com \
  --auth-type oauth2 \
  --auth-token-url https://<your-idp>/oauth/token \
  --auth-client-id "$CLIENT_ID" --auth-client-secret "$CLIENT_SECRET" \
  --endpoint "GET /users"
```

#### Verify the token before you commit to it

`--verify` probes the first endpoint with the pushed auth and reports whether
the token actually works (exit 2 on a bad/expired token):

```bash
liveapisec push --name my-api --base-url https://api.example.com \
  --auth-type bearer --auth-token "$TOKEN" \
  --endpoint "GET /users" --verify
# → verify: GET https://api.example.com/users → 200 ✓
#   or: verify: GET https://api.example.com/users → 401 ✗ auth failed — ...
```

> Network errors from `--verify` are informational — your machine may not reach
> the API while our scanner can; what matters is the auth result (2xx vs 401/403).

Output:

```
site 65f...abc: my-api — 2 endpoints, auth=none
export SITE_ID=65f...abc
```

### 2. `push-code` — scan your source code and push the endpoints

Point the CLI at a repo/folder and it detects the framework, extracts the API
endpoints from the code and pushes them — no running site or OpenAPI spec needed.

```bash
cd my-project
liveapisec push-code --dir . --name my-api --base-url https://api.example.com
```

- Auto-detected frameworks: **FastAPI**, **Flask**, **Django**, **Next.js**
  (`app/api` + `pages/api`), **NestJS** (`@Controller`/`@Get`), **Express**
  (`app.get`), **Laravel**, generic **PHP** (`$app->get`, Slim, Lumen),
  **Spring** (`@GetMapping`, Java), **Go** (Gin, Echo, Fiber, Chi, gorilla/mux,
  `net/http`) and **Rust** (axum, actix-web, rocket, warp).
- Scan a git repository straight from a URL (https / ssh / local path) —
  it is shallow-cloned to a temp dir and cleaned up afterwards:

```bash
liveapisec push-code --repo git@github.com:acme/my-api.git \
  --name my-api --base-url https://api.example.com
```

- Preview before pushing (no API key needed):

```bash
liveapisec push-code --dir . --name my-api --base-url https://api.example.com --dry-run
liveapisec push-code --dir . --name my-api --base-url https://api.example.com --dry-run --json
```

- Force a framework if auto-detection misses it: `--framework nextjs`.

Output:

```
framework: fastapi (42 files scanned)
found 58 endpoints:
  GET     /users
  POST    /payments
site 65f...abc: my-api — 58 endpoints, auth=none
export SITE_ID=65f...abc
```

> **Note on methods**: FastAPI/Flask/Express/NestJS/Spring/Laravel/Go/Rust carry
> the HTTP method in the code. Django `urlpatterns` and Go `net/http` handlers
> do not — those routes are assumed to be `GET`.

### 3. `scan` — run a security test

```bash
# fire and forget (202, does not wait)
liveapisec scan --site SITE_ID --branch main --commit "$GITHUB_SHA"

# wait for the result and fail the build on high (CI gate)
liveapisec scan --site SITE_ID --branch main --commit "$SHA" \
  --wait --fail-on high
```

- `--wait` — polls until the scan finishes (default timeout 600 s,
  interval 3 s; change with `--timeout` / `--poll-interval`).
- `--fail-on high` — **exit code 1** when a finding of severity `high`/`critical`
  is found; `--fail-on critical` only for criticals; omit it → always exit 0
  (except errors).

### 4. `status` — site status + recent scans

```bash
liveapisec status --site SITE_ID
```

### 5. `findings` — scan results

```bash
liveapisec findings --site SITE_ID --scan SCAN_ID
liveapisec findings --site SITE_ID --scan SCAN_ID --json   # raw data (for agents/AI)
```

### 6. `sites` — site details

```bash
liveapisec sites --site SITE_ID
```

### 7. `scans` — full test (scan) history for a site

See every security test ever run on a site (status, branch/commit, tests run,
findings by severity) — useful for an agent that wants to know what was tested,
when, and with what result:

```bash
liveapisec scans --site SITE_ID
# scan 65f...001  status=completed  branch=main  commit=abc  tests=42  findings=3 (high=1 medium=2)
# scan 65f...002  status=failed     branch=main

liveapisec scans --site SITE_ID --json        # raw list (for scripts / agents)
liveapisec scans --site SITE_ID --limit 5     # only the 5 most recent
```

### 8. `projects` — last test status per project (no dashboard needed)

See every project, its sites and the **last security test result** straight in the
terminal — no need to open the dashboard:

```
$ liveapisec projects
svc
  api-a  https://a.example.com  last test: completed · 42 tests · 3 findings (high=1 medium=2)
  api-b  https://b.example.com  last test: failed
mobile
  api-c  https://c.example.com  last test: no test yet

# JSON (for scripts / agents)
liveapisec projects --json

# Only one project
liveapisec projects --project svc
```

---

> **Full documentation:** see the in-browser docs at **https://liveapisec.com/docs**
> (install, config, every command, auth/OAuth2, exit codes, GitHub Actions, SDK).

---

## GitHub Actions — full example (gate on push)

```yaml
name: liveapisec
on: push
jobs:
  security-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with: { python-version: "3.12" }
      - name: Install CLI
        run: pip install "liveapisec @ git+https://github.com/LiveApiSec/liveapisec.git"
      - name: Push API + run security test (gate on high)
        env:
          LIVEAPISEC_API_KEY: ${{ secrets.LIVEAPISEC_KEY }}
        run: |
          liveapisec push --name my-api --base-url "$BASE_URL" \
            --endpoint "GET /users" --endpoint "POST /payments"
          liveapisec scan --site "$SITE_ID" \
            --branch "${GITHUB_REF#refs/heads/}" --commit "$GITHUB_SHA" \
            --wait --fail-on high
```

> **Why is push safe?** Push is idempotent (name+base_url → the same site), so
> the next build does not create junk — it updates endpoints and the token, and
> the next `scan` tests the latest state.

---

## Exit codes

| Code | Meaning |
|------|---------|
| 0    | OK (no findings at/above the threshold, or no `--fail-on`) |
| 1    | Gate failed — findings found at/above `--fail-on` |
| 2    | Usage error / API error / missing key |

---

## Development / tests

```bash
pip install -e ./cli[dev]
cd cli && python -m pytest tests/ -q
```

## SDK (API)

### Python

Besides the CLI, the package also exports a client for scripts:

```python
from liveapisec import LiveAPISec

api = LiveAPISec()  # LIVEAPISEC_API_KEY from env
site = api.create_site("my-api", "https://api.example.com",
                       endpoints=[{"method": "GET", "path": "/users"}])
scan = api.trigger_scan(site["site_id"], branch="main", commit="abc")
done = api.wait_for_scan(site["site_id"], scan["scan_id"])
blocked = LiveAPISec.findings_above(done["findings"], "high")
```

### From any other language — plain REST

Not on Python? The endpoints behind the CLI are a standard REST API. Call them
with **curl**, Node `fetch`, Go, Java, Ruby… anything that speaks HTTP — you get
the same result as the CLI (endpoints pushed, scans run, findings readable by
your agent or CI):

```bash
# push a site + endpoints from any language
curl -X POST $LIVEAPISEC_API_URL/developers/sites \
  -H "Authorization: Bearer $LIVEAPISEC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"my-api","base_url":"https://api.example.com",
       "endpoints":[{"method":"GET","path":"/users"}]}'

# trigger a scan
curl -X POST $LIVEAPISEC_API_URL/developers/sites/$SITE_ID/scans \
  -H "Authorization: Bearer $LIVEAPISEC_API_KEY" \
  -d '{"branch":"main","commit":"abc123"}'
```

---

## Instructions for AI coding assistants (Copilot, Cursor, etc.)

Copy-paste the block below into your AI assistant (GitHub Copilot, Cursor,
Windsurf…) to let it use the LiveAPISec CLI on your behalf.

````markdown
You can use the `liveapisec` CLI (https://pypi.org/project/liveapisec/) to
push API specifications, run security scans and read results against the
LiveAPISec platform. It works with APIs in ANY language/framework (not just
Python) — use `push-code` to extract endpoints from source, or
`push --openapi-url` for an OpenAPI spec.

Environment:
- `LIVEAPISEC_API_KEY` — dev API key (las_dev_...), usually already set.
- `LIVEAPISEC_API_URL` — API base URL (default: https://liveapisec.com).
- `SITE_ID` — the site id returned by `liveapisec push` / `liveapisec sites`.

Fetch information about the portal (to diagnose and fix issues):
- `liveapisec projects`              — every project + last test status
- `liveapisec scans --site <id>`    — full test history for a site (--json for raw)
- `liveapisec status --site <id>`   — site status + recent scans
- `liveapisec sites --site <id>`    — site details
- `liveapisec findings --site <id> --scan <scan_id>`  — findings (--json for raw)

Language note: the CLI is written in Python, but it tests APIs built in ANY
language/framework — Python, Node.js, Go, Rust, Java, PHP, Ruby, .NET, etc.
Use `liveapisec push-code` to auto-extract endpoints from the source
(FastAPI, Flask, Django, Next.js, NestJS, Express, Laravel, PHP/Slim, Spring,
Go, Rust), or `push --openapi-url` for any API that exposes an OpenAPI spec.

Workflow:
1. Push the API under test (idempotent — safe to repeat):
   `liveapisec push --name <name> --base-url <url> --endpoint "METHOD /path" [--endpoint ...] [--openapi-url <url>] [--auth-type jwt|bearer|cookie|api_key --auth-token <token>]`
2. Run a security scan and wait for the result:
   `liveapisec scan --site <site_id> --branch <branch> --commit <sha> --wait`
3. Read findings (severity, title, target):
   `liveapisec findings --site <site_id> --scan <scan_id>` (add `--json` for raw JSON).

Self-repair loop (fix an issue from our test, end-to-end):
1. See what failed: `liveapisec projects`
2. Find the failed scan: `liveapisec scans --site <site_id>`
3. Read the findings: `liveapisec findings --site <site_id> --scan <scan_id> --json`
4. Fix the code (e.g. add a security-header middleware), commit.
5. Re-push (idempotent) and re-run the gate:
   `liveapisec push --name <name> --base-url <url> --endpoint "GET /x"`
   `liveapisec scan --site <site_id> --branch <branch> --commit <sha> --wait --fail-on high`
6. Confirm the gate is green: `liveapisec projects`

Rules:
- Never print or commit the API key; use the environment variable.
- If a scan fails, read the findings, fix the code, re-push and re-scan.
- Push is idempotent, so re-running it is always safe.
- Exit code 1 from `scan --wait --fail-on <sev>` means the gate failed
  (findings at/above that severity); exit 2 means usage/API error.
````
