---
title: Your First Request
product: trilio-share-protection
doc_type: guide
version: master
source: git2docs (code-derived, validation-filtered)
canonical: https://git2docs.com/murali-balcha/docs/trilio-share-protection/trilio-share-protection-/first-request
---

# Your First Request

_A minimal working example using curl or an HTTP client_

## Overview

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.

## Prerequisites

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`, and `OS_USER_DOMAIN_NAME` at minimum).
- **The Abacá API endpoint URL** — the base URL of the `abaca-api` service, for example `https://abaca.example.com`. The `/v1` prefix 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-abacaclient` installed** if you want to use the SDK or the `openstack share protection` CLI (see Installation below).
- **Network access** from your workstation to both the Keystone endpoint and the `abaca-api` endpoint.

## Installation

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**

```console
pip install python-abacaclient
```

**Step 2 — Verify the CLI plugin is registered**

After installation, the `openstack` command should recognise the `share protection` subcommand group:

```console
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**

```console
git clone <repository-url>
cd python-abacaclient
pip install -e '.[test]'
```

## Configuration

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.

## Usage

### Step 1 — Obtain a Keystone token

Abacá authenticates every request via the `X-Auth-Token` header. Obtain a project-scoped token from Keystone:

```console
export OS_TOKEN=$(openstack token issue -f value -c id)
```

You can verify it was set:

```console
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.

```console
curl -s \
  -H "X-Auth-Token: $OS_TOKEN" \
  "${ABACA_ENDPOINT}/v1/targets" | python3 -m json.tool
```

A successful response looks like:

```json
{
  "targets": []
}
```

### Step 3 — Make the same request with the Python SDK

```python
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:

```console
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
```

## Examples

### Example 1 — List backup targets (curl)

Confirm API reachability and authentication with the simplest read-only call.

```console
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):**

```json
{
  "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.

```python
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)

```console
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`:

```python
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`).

```console
curl -s \
  -H "X-Auth-Token: $OS_TOKEN" \
  "${ABACA_ENDPOINT}/v1/jobs" | python3 -m json.tool
```

**Expected output shape:**

```json
{
  "jobs": [
    {
      "id": "d4f2a1c0-...",
      "status": "available",
      "error_category": null,
      "created_at": "2024-06-01T12:00:00Z"
    }
  ]
}
```

## Troubleshooting

### `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:**
1. Re-issue the token: `export OS_TOKEN=$(openstack token issue -f value -c id)`
2. Confirm `OS_AUTH_URL` is reachable: `curl -s $OS_AUTH_URL`
3. Confirm the header is being sent: add `-v` to your `curl` command and look for `X-Auth-Token` in 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:**
1. Verify the endpoint is correct and reachable: `curl -v "${ABACA_ENDPOINT}/v1/targets"`
2. If using the local Docker Compose dev stack, confirm the containers are running: `docker compose ps`
3. Check that port 443 (or whichever port `abaca-api` listens 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:**
1. Confirm both packages are in the same environment: `pip show python-abacaclient python-openstackclient`
2. Reinstall: `pip install --force-reinstall python-abacaclient`
3. 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:
```python
# 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"` to `Client()`
- For the CLI: set `OS_CACERT=/path/to/ca-bundle.pem` in your environment

Do **not** use `-k` / `--insecure` in production — it disables certificate verification entirely.
