Skip to content
OUTIS DOCS

Quickstart

This page takes you from nothing to a decision in your terminal. You need an organization with at least one operator who has claimed a box.

  1. In the dashboard, open your organization’s keys page and generate a key with the propose and read scopes. The secret is shown once, so store it before you leave the page.

    export OUTIS_KEY=<the token you just generated>
  2. Every organization starts with the GitHub integration’s actions, so deploy.production works on a fresh one.

    curl -X POST "https://api.outis.tech/v1/requests" \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer $OUTIS_KEY" \
      -H "Idempotency-Key: quickstart-8d93f71" \
      -d '{
        "action":    "deploy.production",
        "requester": "keith",
        "params":    { "repo": "acme/payments-api", "env": "production", "sha": "8d93f71" }
      }'

    The answer is a 202 with the request itself, the same body you’ll read the decision from:

    {
      "server_now": <epoch ms>,
      "request": {
        "id":             "req-4f2a9c1b8d7e6f50",
        "action":         "deploy.production",
        "requester":      "keith",
        "operation_hash": "sha256:54feb247e0ae56c01d430beb1b1c4c604384ca91832a1ccb435fe2753fb2be9e",
        "state":          "notified",
        "live":           true,
        "outcome":        null,
        "approvers":      [],
        "params":         { "repo": "acme/payments-api", "env": "production", "sha": "8d93f71" },
        "created_at":     <epoch ms>,
        "decided_at":     null
      }
    }

    The eligible operators now have their codes, and their boxes are drawing the request. Run the same call again and you get the same request back, because the Idempotency-Key matches.

  3. An operator enters their code on the box and turns the key. For deploy.production that’s two operators inside one twenty second window, neither of them the requester.

  4. curl "https://api.outis.tech/v1/requests/req-4f2a9c1b8d7e6f50" \
      -H "Authorization: Bearer $OUTIS_KEY"

    outcome is null while the request is live and one of authorized, denied, expired or aborted once it isn’t. Act on authorized only, use the params from the answer, and check the hash before you run anything. The SDKs’ assertAuthorized (assert_authorized in Python) does both checks in one read. Operation hash covers the hash itself.