# API Overview

DanubeData provides a comprehensive RESTful API that allows you to programmatically manage all your infrastructure resources.

## Interactive API Documentation

Our interactive API documentation is available at: **`/docs/api`**

You can access it directly by visiting:
- **Production:** `https://danubedata.ro/docs/api`

Our interactive API documentation provides:

- **Complete endpoint reference** for all API v1 operations
- **Try It functionality** - test endpoints directly in your browser
- **Request/response examples** for every endpoint
- **Authentication testing** with your API tokens
- **OpenAPI 3.0 specification** for integration tools

## Quick Start

### 1. Get Your API Token

1. Navigate to **API Tokens** in your account settings
2. Click **Create New Token**
3. Give it a descriptive name
4. Select the appropriate permissions
5. Choose the project scope — **This project only** (default) or **All my projects**
6. Copy the token (shown only once)

### 2. Make Your First Request

```bash
curl -H "Authorization: Bearer YOUR_TOKEN_HERE" \
     https://danubedata.ro/api/v1/vps
```

**Note**: Ensure your API token has the appropriate permissions (e.g., `vps:read`) for the endpoints you want to access.

### 3. Explore the Documentation

Visit `/docs/api` to:
- Browse all available endpoints
- See detailed request/response formats
- Test endpoints with your token
- Download the OpenAPI specification

## API Base URL

```
Production: https://danubedata.ro/api/v1
```

All API requests should be made to this base URL followed by the specific endpoint path.

## Authentication

All API requests require authentication using a bearer token:

```
Authorization: Bearer YOUR_TOKEN_HERE
```

Learn more about authentication in the [Authentication Guide](https://docs.danubedata.ro/api-authentication).

## Available Resources

The API provides access to manage:

### Infrastructure
- **VPS Instances** - Create and manage virtual private servers
- **Database Instances** - PostgreSQL, MySQL, and MariaDB databases (with read replicas)
- **Cache Instances** - Redis, Valkey, and Dragonfly in-memory stores
- **Queue Instances** - managed RabbitMQ message brokers
- **Parameter Groups** - reusable database/cache configuration presets

### Applications
- **Serverless Containers** - deploy and manage scale-to-zero containers
- **Static Sites** - managed static site hosting with custom domains

### Storage
- **Object Storage** - S3-compatible storage buckets
- **Access Keys** - S3 credentials management

### Networking
- **Firewalls** - Configure security rules
- **SSH Keys** - Manage access credentials

### Operations
- **Snapshots** - Backup and restore operations
- **Webhooks** - Event notifications
- **Metrics** - Resource monitoring

## Connection Endpoints

Database and cache instances expose two different ports, and mixing them up
produces an endpoint that does not work:

Every instance has a **private** endpoint. Enabling public DNS adds a second,
**public** one; it never replaces the private one.

| Field | Plane | Meaning |
|---|---|---|
| `internal_host` / `internal_port` / `internal_endpoint` | Private | The in-cluster Service on the engine port. Always present, never changes when you enable or disable public DNS. |
| `dns_hostname` / `dns_port` / `public_endpoint` | Public | The DNS hostname and the port allocated for it on the shared load balancer. `null` when public DNS is off. |
| `connection_host` / `connection_port` | Whichever applies | The pair you should connect to right now: public when public DNS is enabled, private otherwise. |
| `port` | Private | The **engine** port (6379, 5432, 3306). Unchanged by public DNS — kept for backwards compatibility. |
| `endpoint` | Whichever applies | `connection_host:connection_port`, as a single string. |

**Always use `connection_host` with `connection_port`.** They are resolved
together, so they can never disagree. DNS records cannot encode a port, so
resolving a public hostname tells you nothing about which port to use — and the
engine port on the public load balancer belongs to a different instance.

`port` keeps its original meaning and is unaffected by enabling public DNS, so
existing automation that reads it for private-network connections is unchanged.

All of these fields are additive: nothing that existed before was renamed,
removed, or given a new meaning, so existing integrations keep working unchanged.

Credentials, including the ready-made `connection_info` URL, come from:

- `GET /api/v1/database/{id}/credentials`
- `GET /api/v1/cache/{id}/connection-info` (canonical)
- `GET /api/v1/cache/{id}/credentials` — compatibility alias returning the
  identical payload, with the same authorization, token permission and rate
  limit as the canonical route

Enabling public DNS (`POST /api/v1/{database,cache}/{id}/dns`) returns both
`dns_hostname` and the allocated `dns_port`.

For databases, `username`/`password` are the **superuser** (`postgres` on
PostgreSQL, `root` on MySQL/MariaDB) wherever the platform can resolve them, so
these credentials can create roles, extensions and databases. `database` is the
database that actually exists on the cluster — for a cluster created without an
explicit name, that is the bootstrap database, not `null`.

Read endpoints (read replicas, and Redis Sentinel) are reachable on the **private
network only**. They have no public load-balancer frontend, so they keep the
engine port even while public DNS is enabled.

Rotating a database or cache password is not supported through the API.

## Response Format

All API responses are returned in JSON format:

```json
{
  "data": [...],
  "pagination": {
    "current_page": 1,
    "last_page": 5,
    "per_page": 15,
    "total": 72
  }
}
```

## API Token Permissions

API tokens support granular, resource-specific permissions to control access to different parts of the API. When creating an API token, you can select which permissions to grant:

### Available Scopes

| Resource | Read Permission | Write Permission | Delete Permission |
|----------|----------------|------------------|-------------------|
| VPS Instances | `vps:read` | `vps:write` | `vps:delete` |
| Databases | `database:read` | `database:write` | `database:delete` |
| Cache Instances | `cache:read` | `cache:write` | `cache:delete` |
| Object Storage | `storage:read` | `storage:write` | `storage:delete` |
| Firewalls | `firewall:read` | `firewall:write` | `firewall:delete` |
| Snapshots | `snapshot:read` | `snapshot:write` | `snapshot:delete` |
| SSH Keys | `ssh-key:read` | `ssh-key:write` | `ssh-key:delete` |
| Webhooks | `webhook:read` | `webhook:write` | - |
| Serverless Containers | `serverless:read` | `serverless:write` | `serverless:delete` |
| Static Sites | `static-site:read` | `static-site:write` | `static-site:delete` |

### Permission Mapping

- **Read**: Allows viewing/listing resources and their details
- **Write**: Allows creating, updating, and performing actions on resources
- **Delete**: Allows deleting resources

### Default Permissions

New API tokens are created with basic read permissions by default:
- `vps:read`
- `database:read`
- `cache:read`
- `storage:read`
- `static-site:read`

### Predefined Roles

- **Editor**: Read and write access to all resources
- **Admin**: Full access including delete permissions

## Rate Limiting

API requests are rate-limited based on your account tier. Rate limit information is included in response headers:

- `X-RateLimit-Limit` - Maximum requests per window
- `X-RateLimit-Remaining` - Remaining requests
- `X-RateLimit-Reset` - Reset timestamp

## Error Handling

The API uses standard HTTP status codes:

- `200 OK` - Request succeeded
- `201 Created` - Resource created successfully
- `204 No Content` - Success with no response body
- `400 Bad Request` - Invalid request parameters
- `401 Unauthorized` - Missing or invalid authentication
- `403 Forbidden` - Insufficient permissions or token scopes
- `404 Not Found` - Resource not found
- `422 Unprocessable Entity` - Validation error
- `429 Too Many Requests` - Rate limit exceeded
- `500 Internal Server Error` - Server error

Error responses include details:

```json
{
  "message": "The given data was invalid.",
  "errors": {
    "name": ["The name field is required."]
  }
}
```

## SDK and Client Libraries

You can generate client SDKs in any language using our OpenAPI specification:

```bash
# Download the spec
curl https://danubedata.ro/docs/api.json > api-spec.json

# Generate a Python client
openapi-generator-cli generate \
  -i api-spec.json \
  -g python \
  -o danubedata-python-client

# Or JavaScript/TypeScript
openapi-generator-cli generate \
  -i api-spec.json \
  -g typescript-axios \
  -o danubedata-ts-client
```

## Next Steps

To access the interactive API documentation, open a new browser tab and navigate to:
- **`/docs/api`** (or click your browser's address bar and type this path)

Or explore these guides:
- **Authentication Guide** - Learn about API tokens  
- **Rate Limits** - Understand usage limits

## Need Help?

- Visit `/docs/api` in your browser for detailed examples and interactive testing
- Contact our support team through the support portal
- Join our community Discord for developer discussions

