# Quickstart

> Get a token, apply your first action, and read the object it produced.

This walks the full write path: authenticate, **apply an action**, and read the object it changed. Aerandil has no generic “create object” call — every write is a named, validated [action](/guides/ontology-model/#actions).

## Prerequisites

- A service-account `client_id` / `client_secret`.
- Its grant includes `objects:read` and the action scope you intend to use (here, `actions:hospitality.action.apply_payment:apply`). See [Authentication](/guides/authentication/).

1. **Get a token.**

   ```bash
   ACCESS_TOKEN=$(curl -s -X POST https://api.aerandil.com/oauth/token \
     -H "Content-Type: application/x-www-form-urlencoded" \
     -d grant_type=client_credentials \
     -d client_id="$AERANDIL_CLIENT_ID" \
     -d client_secret="$AERANDIL_CLIENT_SECRET" \
     -d scope="objects:read actions:hospitality.action.apply_payment:apply" \
     | jq -r .access_token)
   ```

2. **(Optional) Discover what you can apply.**

   ```bash
   curl https://api.aerandil.com/v1/action-types \
     -H "Authorization: Bearer $ACCESS_TOKEN"
   ```

   Each action’s full parameter schema lives in the [API reference](/api/).

3. **(Optional) Validate before applying.** Every action has a dry-run twin that runs validation without mutating anything:

   ```bash
   curl -X POST https://api.aerandil.com/v1/actions/hospitality.action.apply_payment/validate \
     -H "Authorization: Bearer $ACCESS_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{ "params": { "amount": { "amount": "120.00", "currency": "USD" } } }'
   ```

4. **Apply the action.** Send an `Idempotency-Key` so a retry can’t double-apply:

   ```bash
   curl -X POST https://api.aerandil.com/v1/actions/hospitality.action.apply_payment/apply \
     -H "Authorization: Bearer $ACCESS_TOKEN" \
     -H "Content-Type: application/json" \
     -H "Idempotency-Key: $(uuidgen)" \
     -d '{ "params": { "amount": { "amount": "120.00", "currency": "USD" } } }'
   ```

   A `200` returns the affected object(s) and a new `version`. A `422` means the params failed validation; a `409` is a conflict (e.g. a concurrency or business-rule clash).

5. **Read the result.** Reads are typed by object type:

   ```bash
   curl https://api.aerandil.com/v1/object-types/hospitality.folio/objects/$FOLIO_ID \
     -H "Authorization: Bearer $ACCESS_TOKEN"
   ```

## Concurrency

Every object carries a monotonic `version`, returned as a strong `ETag` on a read. There is no generic write to guard: an action reads its target’s current state when it runs, and a change that no longer fits that state is refused with `409` and the reason. Keep the version you read to tell whether an object has moved; apply an action to move it. See [Usage guidelines](/guides/usage-guidelines/).

## Next

- [The ontology model](/guides/ontology-model/) — objects, links, and actions.
- [API reference](/api/) — every action’s full parameter schema.
- [MCP server](/mcp/overview/) — drive these same actions from an AI agent.

---

Source: https://developers.aerandil.com/guides/quickstart/
