Your First Request
A minimal working example using curl or an HTTP client
This page walks you through making your first authenticated request to the Trilio Share Protection (Abacá) REST API. By the end, you will have obtained a Keystone token, listed your backup targets with curl, and made the equivalent call using the python-abacaclient SDK — giving you a working foundation for every other workflow in the product. Getting this baseline right matters because every Abacá operation, whether creating a protection policy, triggering an on-demand backup, or monitoring a job, flows through the same authentication model and base URL structure covered here.
Before you begin, make sure you have the following:
- A running Abacá deployment — either the local Docker Compose dev stack or a production control plane on OpenShift ≥ 4.12.
- OpenStack Keystone — you need a valid project-scoped Keystone token or the credentials to obtain one (
OS_AUTH_URL,OS_USERNAME,OS_PASSWORD,OS_PROJECT_NAME, andOS_USER_DOMAIN_NAMEat minimum). - The Abacá API endpoint URL — the base URL of the
abaca-apiservice, for examplehttps://abaca.example.com. The/v1prefix is appended automatically by the SDK and must not be included in the base URL you configure. curl≥ 7.x (for the raw HTTP examples) or Python ≥ 3.11 (for the SDK examples).python-abacaclientinstalled if you want to use the SDK or theopenstack share protectionCLI (see Installation below).- Network access from your workstation to both the Keystone endpoint and the
abaca-apiendpoint.
If you only want to use curl, skip to the Configuration section — no installation is required.
To use the Python SDK or the openstack share protection CLI, install python-abacaclient:
Step 1 — Install from PyPI
pip install python-abacaclient
Step 2 — Verify the CLI plugin is registered
After installation, the openstack command should recognise the share protection subcommand group:
openstack share protection --help
You should see a list of subcommands including target list, backup create, job show, and others. If you see 'share protection' is not an openstack command, ensure python-abacaclient is installed into the same Python environment as python-openstackclient.
Step 3 — (Optional) Install in editable mode for development
git clone <repository-url>
cd python-abacaclient
pip install -e '.[test]'
All configuration for your first request comes from two sources: your OpenStack authentication environment and the Abacá endpoint URL.
OpenStack authentication environment variables
Set these before running any command. They are consumed by both curl-based flows (to obtain a token) and by the openstack CLI.
| Variable | Required | Example | Purpose |
|---|---|---|---|
OS_AUTH_URL | Yes | https://keystone.example.com/v3 | Keystone identity endpoint |
OS_USERNAME | Yes | jsmith | Your OpenStack username |
OS_PASSWORD | Yes | (your password) | Your OpenStack password |
OS_PROJECT_NAME | Yes | my-project | Project to scope the token to |
OS_USER_DOMAIN_NAME | Yes | Default | Domain of your user account |
OS_PROJECT_DOMAIN_NAME | Yes | Default | Domain of your project |
Abacá endpoint
| Variable | Required | Example | Purpose |
|---|---|---|---|
ABACA_ENDPOINT | Yes (for curl flows) | https://abaca.example.com | Base URL of the abaca-api service — without /v1 |
SDK constructor parameters
When constructing a Client object directly in Python, the relevant parameters are:
| Parameter | Default | Description |
|---|---|---|
endpoint | (required) | Base URL of abaca-api. /v1 is appended automatically. |
token | None | Keystone token sent as X-Auth-Token. Use this for simple scripts. |
session | None | A keystoneauth1.Session. Takes precedence over token when provided — recommended for production code. |
ca_cert | None | Path to a CA bundle for TLS verification. Set this when abaca-api is behind a private certificate authority. |
When both token and session are omitted, the client will make unauthenticated requests and the API will return 401 Unauthorized. Always supply one of the two.
Step 1 — Obtain a Keystone token
Abacá authenticates every request via the X-Auth-Token header. Obtain a project-scoped token from Keystone:
export OS_TOKEN=$(openstack token issue -f value -c id)
You can verify it was set:
echo $OS_TOKEN
Step 2 — Make your first request with curl
List your backup targets. If you have not registered any yet, the response will be an empty list — that is expected and confirms the API is reachable and your token is valid.
curl -s \
-H "X-Auth-Token: $OS_TOKEN" \
"${ABACA_ENDPOINT}/v1/targets" | python3 -m json.tool
A successful response looks like:
{
"targets": []
}
Step 3 — Make the same request with the Python SDK
from abacaclient.client import Client
import os
client = Client(
endpoint=os.environ["ABACA_ENDPOINT"],
token=os.environ["OS_TOKEN"],
)
results = client.target_list()
print(results) # {'targets': []}
Step 4 — Make the same request with the OpenStack CLI
If you have python-abacaclient installed and your OS_* environment variables set, the CLI handles token acquisition automatically:
openstack share protection target list
Understanding the base URL
The abaca-api service exposes all tenant-facing endpoints under /v1. The SDK appends this prefix automatically — you supply only the scheme and host. When constructing curl commands directly, include /v1 in the path yourself:
https://abaca.example.com/v1/targets ← targets collection
https://abaca.example.com/v1/policies ← policies collection
https://abaca.example.com/v1/backups ← backups collection
https://abaca.example.com/v1/jobs ← jobs collection
Example 1 — List backup targets (curl)
Confirm API reachability and authentication with the simplest read-only call.
export OS_TOKEN=$(openstack token issue -f value -c id)
export ABACA_ENDPOINT=https://abaca.example.com
curl -s \
-H "X-Auth-Token: $OS_TOKEN" \
"${ABACA_ENDPOINT}/v1/targets" | python3 -m json.tool
Expected output (no targets registered yet):
{
"targets": []
}
Example 2 — List backup targets (Python SDK)
The SDK raises abacaclient.exceptions.AbacaClientError on any non-2xx response, so you can handle authentication failures explicitly.
import os
from abacaclient.client import Client
from abacaclient.exceptions import AbacaClientError
client = Client(
endpoint=os.environ["ABACA_ENDPOINT"],
token=os.environ["OS_TOKEN"],
)
try:
result = client.target_list()
targets = result.get("targets", [])
print(f"Found {len(targets)} backup target(s).")
for t in targets:
print(f" {t['id']} {t['name']} status={t['status']}")
except AbacaClientError as exc:
print(f"Request failed: HTTP {exc.status} — {exc}")
Expected output (no targets registered yet):
Found 0 backup target(s).
Example 3 — List backup targets (OpenStack CLI)
export ABACA_ENDPOINT=https://abaca.example.com
# OS_* variables already set from your clouds.yaml or RC file
openstack share protection target list
Expected output (no targets registered yet):
+----+------+----------+--------+--------+
| id | name | endpoint | bucket | status |
+----+------+----------+--------+--------+
+----+------+----------+--------+--------+
Example 4 — Inspect a failed request
If you supply a bad or expired token, the API returns 401. The SDK surfaces this as an AbacaClientError:
from abacaclient.client import Client
from abacaclient.exceptions import AbacaClientError
client = Client(endpoint="https://abaca.example.com", token="bad-token")
try:
client.target_list()
except AbacaClientError as exc:
print(f"HTTP status : {exc.status}")
print(f"Error detail: {exc}")
Expected output:
HTTP status : 401
Error detail: ...
Example 5 — List jobs (curl)
Once you start triggering backups or restores, you will poll the jobs collection to track progress through the job state machine (queued → provisioning_network → … → available).
curl -s \
-H "X-Auth-Token: $OS_TOKEN" \
"${ABACA_ENDPOINT}/v1/jobs" | python3 -m json.tool
Expected output shape:
{
"jobs": [
{
"id": "d4f2a1c0-...",
"status": "available",
"error_category": null,
"created_at": "2024-06-01T12:00:00Z"
}
]
}
401 Unauthorized on every request
Symptom: Every curl or SDK call returns HTTP 401, or the CLI prints an authentication error.
Likely cause: Your Keystone token has expired (tokens are typically valid for one hour), the X-Auth-Token header was not sent, or the OS_AUTH_URL points to the wrong Keystone endpoint.
Fix:
- Re-issue the token:
export OS_TOKEN=$(openstack token issue -f value -c id) - Confirm
OS_AUTH_URLis reachable:curl -s $OS_AUTH_URL - Confirm the header is being sent: add
-vto yourcurlcommand and look forX-Auth-Tokenin the request headers.
curl: (6) Could not resolve host or connection refused
Symptom: curl fails immediately with a DNS resolution error or Connection refused.
Likely cause: ABACA_ENDPOINT is set to the wrong hostname, the abaca-api service is not running, or there is a network/firewall issue between your workstation and the API.
Fix:
- Verify the endpoint is correct and reachable:
curl -v "${ABACA_ENDPOINT}/v1/targets" - If using the local Docker Compose dev stack, confirm the containers are running:
docker compose ps - Check that port 443 (or whichever port
abaca-apilistens on) is open in your firewall or security group.
'share protection' is not an openstack command
Symptom: Running openstack share protection target list prints an error saying the subcommand is not recognised.
Likely cause: python-abacaclient is not installed in the same Python environment as python-openstackclient, or the package is installed but the entry points have not been registered.
Fix:
- Confirm both packages are in the same environment:
pip show python-abacaclient python-openstackclient - Reinstall:
pip install --force-reinstall python-abacaclient - Verify registration:
openstack share protection --help
SDK raises AbacaClientError with HTTP 404 on /v1/targets
Symptom: The client raises an error indicating a 404 Not Found when calling client.target_list().
Likely cause: The endpoint passed to Client() already contains /v1, causing the SDK to construct the URL as /v1/v1/targets.
Fix: Pass only the scheme and host to Client(). The SDK appends /v1 automatically:
# Correct
client = Client(endpoint="https://abaca.example.com", token=token)
# Wrong — do not include /v1
# client = Client(endpoint="https://abaca.example.com/v1", token=token)
TLS certificate verification failure
Symptom: curl exits with SSL certificate problem: unable to get local issuer certificate, or the SDK raises a connection error mentioning SSL.
Likely cause: The abaca-api service is behind a private certificate authority whose root certificate is not in your system trust store.
Fix:
- For
curl: add--cacert /path/to/ca-bundle.pem - For the SDK: pass
ca_cert="/path/to/ca-bundle.pem"toClient() - For the CLI: set
OS_CACERT=/path/to/ca-bundle.pemin your environment
Do not use -k / --insecure in production — it disables certificate verification entirely.