API Integration

Guide for automating deployments and integrating CI/CD pipelines with the DeployAlly REST API.

Overview

The API lets you:

  • List and inspect the template catalog
  • Create definitions (template + inputs + instance metadata)
  • Trigger deployments and track status
  • Run actions on running instances
  • Receive events via webhooks

Environments

Environment Base URL Use
Production https://sys.deployally.com/api/v1 Production systems
Test https://dev.sys.deployally.com/api/v1 Development

Initial Setup

1. Get an API Key

  1. Log in at https://app.deployally.com
  2. SettingsAPI KeysCreate New
  3. Set the minimum required permissions
  4. Copy the key (it won't be shown again)

2. Configure Environment

export DEPLOYALLY_API_URL="https://sys.deployally.com/api/v1"
export DEPLOYALLY_API_KEY="da_xxx"

3. Test

curl -X GET "${DEPLOYALLY_API_URL}/health"
curl -X GET "${DEPLOYALLY_API_URL}/templates" \
  -H "Authorization: Bearer ${DEPLOYALLY_API_KEY}"

Automated Deploy Flow

1. List templates         → GET /templates
2. Inspect template       → GET /templates/<species>
3. Register server        → POST /servers/register   (once)
4. Create definition      → POST /definitions
5. Execute deploy         → POST /deployments/execute
6. Track status           → GET /deployments/<id>
7. List instances         → GET /instances

Full Example

#!/bin/bash
set -euo pipefail

API="${DEPLOYALLY_API_URL}"
KEY="${DEPLOYALLY_API_KEY}"

# 1. Fetch the memos template
TEMPLATE=$(curl -s "${API}/templates/memos" \
  -H "Authorization: Bearer ${KEY}" | jq -r '.data.id')

# 2. Create a definition
DEFINITION=$(curl -s -X POST "${API}/definitions" \
  -H "Authorization: Bearer ${KEY}" \
  -H "Content-Type: application/json" \
  -d "{
    \"species\": \"memos\",
    \"instance_uid\": \"memos-001\",
    \"server_id\": \"srv_123\",
    \"inputs\": {
      \"WEB_HOSTNAME\": \"memos.example.com\"
    },
    \"profile\": \"production\"
  }" | jq -r '.data.id')

# 3. Execute the deploy
DEPLOY=$(curl -s -X POST "${API}/deployments/execute" \
  -H "Authorization: Bearer ${KEY}" \
  -H "Content-Type: application/json" \
  -d "{\"definition_id\": \"${DEFINITION}\"}" | jq -r '.data.id')

# 4. Wait for completion
while true; do
  STATUS=$(curl -s "${API}/deployments/${DEPLOY}" \
    -H "Authorization: Bearer ${KEY}" | jq -r '.data.status')

  case "$STATUS" in
    success)
      echo "Deploy completed"
      break
      ;;
    failed)
      echo "Deploy failed"
      exit 1
      ;;
    *)
      sleep 5
      ;;
  esac
done

Working with Actions

Templates declare post-deploy operations (backups, restart, etc.). The API lets you trigger those operations remotely.

List Available Actions

curl -X GET "${API}/instances/inst_abc/actions" \
  -H "Authorization: Bearer ${KEY}"

Run an Action

EXEC=$(curl -s -X POST "${API}/instances/inst_abc/actions/dump-database/execute" \
  -H "Authorization: Bearer ${KEY}" \
  -H "Content-Type: application/json" \
  -d '{}' | jq -r '.execution.id')

# Track it
while true; do
  STATUS=$(curl -s "${API}/actions/${EXEC}" \
    -H "Authorization: Bearer ${KEY}" | jq -r '.execution.status')

  [ "$STATUS" = "completed" ] && break
  [ "$STATUS" = "failed" ] && exit 1
  sleep 2
done

CI/CD Integration

GitHub Actions

name: Deploy to DeployAlly

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Trigger Deployment
        env:
          DEPLOYALLY_API_KEY: ${{ secrets.DEPLOYALLY_API_KEY }}
        run: |
          curl -X POST "https://sys.deployally.com/api/v1/deployments/execute" \
            -H "Authorization: Bearer ${DEPLOYALLY_API_KEY}" \
            -H "Content-Type: application/json" \
            -d '{"definition_id": "def_app_main"}'

GitLab CI

deploy:
  stage: deploy
  script:
    - |
      curl -X POST "https://sys.deployally.com/api/v1/deployments/execute" \
        -H "Authorization: Bearer ${DEPLOYALLY_API_KEY}" \
        -H "Content-Type: application/json" \
        -d '{"definition_id": "def_app_main"}'
  only:
    - main

Webhooks

Configure webhooks to receive notifications in real time.

Register an Endpoint

curl -X POST "${API}/webhooks/endpoints" \
  -H "Authorization: Bearer ${KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://my-system.com/webhook/deployally",
    "events": [
      "deployment.success",
      "deployment.failed",
      "instance.unhealthy",
      "action.completed"
    ],
    "secret": "my_webhook_secret"
  }'

Receive a Webhook (Python/Flask)

from flask import Flask, request
import hmac
import hashlib

app = Flask(__name__)
WEBHOOK_SECRET = "my_webhook_secret"

@app.route('/webhook/deployally', methods=['POST'])
def handle_webhook():
    signature = request.headers.get('X-DeployAlly-Signature')
    payload = request.get_data()
    expected = hmac.new(
        WEBHOOK_SECRET.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()

    if not hmac.compare_digest(signature, expected):
        return 'Invalid signature', 403

    event = request.json
    event_type = event['type']

    if event_type == 'deployment.success':
        # Notify the team
        pass
    elif event_type == 'instance.unhealthy':
        # Alert / attempt restart
        pass

    return 'OK', 200

Error Handling

Retry with Backoff

import requests
import time

def api_request(method, endpoint, **kwargs):
    url = f"{DEPLOYALLY_API_URL}{endpoint}"
    headers = {
        "Authorization": f"Bearer {DEPLOYALLY_API_KEY}",
        "Content-Type": "application/json"
    }

    for attempt in range(3):
        try:
            response = requests.request(
                method, url, headers=headers, **kwargs
            )

            if response.status_code == 429:
                retry_after = int(response.headers.get('Retry-After', 60))
                time.sleep(retry_after)
                continue

            response.raise_for_status()
            return response.json()

        except requests.exceptions.RequestException:
            if attempt == 2:
                raise
            time.sleep(2 ** attempt)

    raise Exception("Max retries exceeded")

Common Error Codes

Code Cause Action
401 Invalid key Check the API Key
403 No permission Check the key's permissions
404 Resource not found Check the IDs
422 Invalid data Check the payload
429 Rate limit Wait and retry
500 Internal error Retry with backoff

Best Practices

Security

  1. Never expose API Keys in logs, code, or repositories
  2. Use environment variables or secrets managers (HashiCorp Vault, AWS Secrets Manager)
  3. Rotate keys periodically (POST /servers/{id}/rotate-key)
  4. Use the minimum required permissions
  5. Set up an IP allowlist when possible

Performance

  1. Cache templates locally (they change rarely; Cache-Control: max-age=60 on the API)
  2. Use webhooks instead of polling
  3. Group related operations

Resilience

  1. Implement retry with exponential backoff
  2. Handle 429 Rate Limited properly
  3. Validate responses before using them (success: true/false)
  4. Use structured logs to audit automated actions

Next Steps

By Borlot.com.br on 05/06/2026