# Wellbore Genius — PowerShell SDK

Drive the public `/api/public/sdk/v1/*` endpoints from Windows PowerShell 5.1+
or PowerShell 7+. No external modules required — uses built-in
`Invoke-RestMethod`.

## Authentication

Mint an API key in **Settings → API keys**. The recommended way to save it is
the interactive helper (`examples/Set-DownholeApiKey.ps1`) — it reads the key
as a `SecureString`, so nothing lands in your shell history or transcript:

```powershell
# Session-only (safest, default)
.\examples\Set-DownholeApiKey.ps1

# Persist for the current Windows user (survives reboots)
.\examples\Set-DownholeApiKey.ps1 -Scope User

# Persist + pin a preview deployment as the default base URL
.\examples\Set-DownholeApiKey.ps1 -Scope User `
  -BaseUrl "https://project--<project-id>-dev.lovable.app"

# Verify without revealing the key (prints length + prefix only)
.\examples\Set-DownholeApiKey.ps1 -Verify -Scope User

# Remove the key
.\examples\Set-DownholeApiKey.ps1 -Clear -Scope User
```

Or set it manually — never paste the raw key inside a committed script:

```powershell
# Current session only
$Env:DOWNHOLE_API_KEY = "dh_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

# Persist for the current Windows user
[Environment]::SetEnvironmentVariable(
  "DOWNHOLE_API_KEY",
  "dh_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "User"
)
```

Optional base-URL override (defaults to `https://wellboregenius.com`):

```powershell
$Env:DOWNHOLE_BASE_URL = "https://project--<project-id>-dev.lovable.app"
```

Every example script reads `$Env:DOWNHOLE_API_KEY` and throws early if it's
missing, so you never accidentally hit the API unauthenticated.



## Quickstart — solver-spec

```powershell
$headers = @{ Authorization = "Bearer $Env:DOWNHOLE_API_KEY" }
Invoke-RestMethod `
  -Uri "https://wellboregenius.com/api/public/sdk/v1/solver-spec" `
  -Headers $headers
```

## Parent–child analyze

See `examples/Invoke-ParentChildAnalyze.ps1` for a wrapped, parameter-checked
version. Bare `Invoke-RestMethod`:

```powershell
$body = @{
  parents = @(
    @{ id = "P1"; heel = @{x=0; y= 660}; toe = @{x=10000; y= 660}; drawdownPsi = 1000 },
    @{ id = "P2"; heel = @{x=0; y=-660}; toe = @{x=10000; y=-660}; drawdownPsi = 1000 }
  )
  child     = @{ id = "C1"; heel = @{x=0; y=0}; toe = @{x=10000; y=0}; stageCount = 50 }
  reservoir = @{ biotAlpha = 0.85; poissonRatio = 0.22 }
} | ConvertTo-Json -Depth 6

Invoke-RestMethod `
  -Uri     "https://wellboregenius.com/api/public/sdk/v1/parent-child/analyze" `
  -Method  Post `
  -Headers @{ Authorization = "Bearer $Env:DOWNHOLE_API_KEY"; "Content-Type" = "application/json" } `
  -Body    $body
```

## Non-planar 3D

See `docs/sdk/non-planar-3d-powershell.md` for the full walkthrough including
error handling, retries, and saving the per-step history to CSV.

## Marketplace preset bundles (import / export)

Round-trip `MarketplacePresetEnvelope` bundles through the public
validation endpoint (`POST /api/public/sdk/v1/marketplace/bundle`). The
endpoint enforces the canonical envelope shape, dedupes by `id`, caps at
500 entries, and returns a per-entry rejection report — the same rules
the in-app `/marketplace` UI applies on file import.

```powershell
# Normalize a local bundle before shipping it to teammates / a gist
.\examples\Export-MarketplacePresets.ps1 `
  -InputPath  .\my-presets-raw.json `
  -OutputPath .\my-presets-normalized.json

# Pull a remote bundle, validate, and prep for drag-and-drop into /marketplace
.\examples\Import-MarketplacePresets.ps1 `
  -SourceUrl  "https://gist.githubusercontent.com/user/id/raw/basin.json" `
  -OutputPath .\ready-to-import.json

# Validate a teammate's file; fail hard if any envelope was rejected
.\examples\Import-MarketplacePresets.ps1 `
  -InputPath  .\from-teammate.json `
  -OutputPath .\ready-to-import.json `
  -FailOnRejected
```

The endpoint is stateless (no shared cloud catalog yet) — it validates
and normalizes bundles so the file you save matches the format the
`/marketplace` UI accepts under **Browse → Import JSON**.

## Files

| Path                                                | Purpose                                                                    |
| --------------------------------------------------- | -------------------------------------------------------------------------- |
| `examples/Set-DownholeApiKey.ps1`                   | Interactive `DOWNHOLE_API_KEY` setup (SecureString, Session/User/Machine). |
| `examples/Invoke-SolverSpec.ps1`                    | Fetch `/solver-spec` (GET, raw response).                                  |
| `examples/Get-SolverSpecReport.ps1`                 | End-to-end `/solver-spec` runner: summary + JSON/CSV save + optional CI gate. |

| `examples/Invoke-ParentChildAnalyze.ps1`            | Wrapped parent–child POST.                                                 |
| `examples/Invoke-NonPlanar3dRun.ps1`                | Non-planar 3D pipeline POST.                                               |
| `examples/Export-MarketplacePresets.ps1`            | Validate + normalize a local marketplace bundle via the API.               |
| `examples/Import-MarketplacePresets.ps1`            | Fetch (or read) a bundle, validate via the API, write import-ready JSON.   |


