Skip to main content

Quickstart

This quickstart uses the current DalyAPI auth flow:
  1. Exchange workspace + user API keys for a JWT.
  2. Use the JWT in Authorization: Bearer ... for protected routes.
  3. Run an energy model sync (default) or async (?async=true) and track status.

1. Set Your API Base URL

Use your deployed API host. In local development, the default is:
export DALY_API_BASE_URL="http://localhost:8000"

2. Exchange API Keys for a JWT

Call POST /auth/token with your workspace and user API keys.
curl -sS -X POST "$DALY_API_BASE_URL/auth/token" \
  -H "Content-Type: application/json" \
  -d '{
    "workspace_id": "WORKSPACE_API_KEY",
    "user_id": "USER_API_KEY"
  }'
Example response:
{
  "access_token": "<jwt>",
  "token_type": "bearer",
  "expires_in": 86400
}

3. Call Protected Endpoints

export DALY_TOKEN="<jwt-from-auth-token>"

curl -sS "$DALY_API_BASE_URL/projects" \
  -H "Authorization: Bearer $DALY_TOKEN"

4. Run an Energy Model (Sync Default)

By default, POST /energymodels runs synchronously. Use ?async=true when you want queued background execution. Current output-shaping controls live in the request body under output:
  • output.timeSeries=true adds plant-level timeSeries data to sync completed responses.
  • output.blockResults=true adds block-level blockTimeSeries data.
  • output.blockIndex filters the returned blockTimeSeries map to one zero-based block but does not reduce execution scope.
  • output.lossBreakdownTimestamps=true implies block-level results and nests timestamped loss detail under blockTimeSeries[<blockIndex>].lossBreakdown.
  • output.fullTimeSeries=true cannot be combined with output.blockResults=true.
Example async call:
curl -sS -X POST "$DALY_API_BASE_URL/energymodels?async=true" \
  -H "Authorization: Bearer $DALY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "locationId": 1,
    "blocks": [
      {
        "inverterId": 1,
        "moduleId": 1,
        "array": {"stringCount": 10, "stringLength": 28},
        "layout": {"arrayType": "fixed", "gcr": 0.4, "azimuth": 180, "axisTilt": 0, "tilt": 25},
        "shading": {"farShading": false, "nearShading": "unlimited", "electricalImpact": false},
        "losses": {
          "moduleQuality": 0.0,
          "mismatch": 0.02,
          "dcohmic": 0.01,
          "lid": 0.01,
          "stringVoltageMismatch": 0.01,
          "invAuxLoss": true,
          "uC": 25,
          "uV": 1.2
        },
        "acSystem": {
          "numberOfInverters": 1,
          "losses": {"acohmicLoss": 0.01, "transformer": {"ironLoss": 0.005, "copperLoss": 0.005}}
        },
        "albedo": {"jan": 0.2, "feb": 0.2, "mar": 0.2, "apr": 0.2, "may": 0.2, "jun": 0.2, "jul": 0.2, "aug": 0.2, "sep": 0.2, "oct": 0.2, "nov": 0.2, "dec": 0.2}
      }
    ]
  }'
Example response:
{
  "result": "success",
  "message": "Energy model queued for processing",
  "energyModelId": 56,
  "revision": "v0003",
  "taskDetails": {
    "message": "Energy model queued for processing",
    "taskId": 1234,
    "schemaMode": "legacy",
    "executionMode": "async_fanout",
    "calculationTime": null,
    "createdAtUtc": "2026-03-03T16:22:03Z",
    "warnings": [],
    "normalizationWarnings": []
  }
}
If you need immediate sync time-series output, set the output flags explicitly on the request body and inspect timeSeries and blockTimeSeries in the completed response. blockTimeSeries keys preserve the original zero-based block numbering, including filtered single-block responses. Each returned block result already represents the full configured numberOfInverters count for that block type, not a single inverter.

5. Poll Task Status

curl -sS "$DALY_API_BASE_URL/tasks/1234" \
  -H "Authorization: Bearer $DALY_TOKEN"
When complete, fetch results:
curl -sS "$DALY_API_BASE_URL/energymodels/56" \
  -H "Authorization: Bearer $DALY_TOKEN"
Task lifecycle is pending -> queued -> running -> completed|failed|cancelled.

6. Edit and Rerun a Saved Model In Place

Imported PVsyst variants from POST /projects/import and previously created energy models both use the same saved-row workflow:
  1. GET /energymodels/{id}?include=inputs
  2. edit the returned saved input JSON
  3. PUT /energymodels/{id}
  4. POST /energymodels/{id}/run
Example:
curl -sS "$DALY_API_BASE_URL/energymodels/56?include=inputs" \
  -H "Authorization: Bearer $DALY_TOKEN"

curl -sS -X PUT "$DALY_API_BASE_URL/energymodels/56" \
  -H "Authorization: Bearer $DALY_TOKEN" \
  -H "Content-Type: application/json" \
  -d @edited-energy-model-input.json

curl -sS -X POST "$DALY_API_BASE_URL/energymodels/56/run?async=true" \
  -H "Authorization: Bearer $DALY_TOKEN"
The rerun stays on energy model 56; it does not create a second row.

7. Response Contracts

For full sync-complete vs queued 200 envelopes, taskDetails fields, and include-token behavior, see:

Where to Learn Input Contracts

Prefer Python Integration?

See the SDK Overview for a resource-oriented client flow with built-in token handling.