{"slug":"api-authentication","title":"API Authentication","description":"All DanubeData API requests require authentication using Laravel Sanctum bearer tokens.","section":"API Reference","url":"https://docs.danubedata.ro/api-authentication","markdown_url":"https://docs.danubedata.ro/api-authentication.md","breadcrumbs":[{"title":"API Reference","slug":null},{"title":"Authentication","slug":"api-authentication"}],"headings":[{"level":1,"title":"API Authentication","id":"api-authentication"},{"level":2,"title":"Creating an API Token","id":"creating-an-api-token"},{"level":3,"title":"Step 1: Navigate to API Tokens","id":"step-1-navigate-to-api-tokens"},{"level":3,"title":"Step 2: Create a New Token","id":"step-2-create-a-new-token"},{"level":3,"title":"Step 3: Save Your Token","id":"step-3-save-your-token"},{"level":2,"title":"Using Your Token","id":"using-your-token"},{"level":3,"title":"In HTTP Headers","id":"in-http-headers"},{"level":3,"title":"Example with cURL","id":"example-with-curl"},{"level":3,"title":"Example with JavaScript/Axios","id":"example-with-javascriptaxios"},{"level":3,"title":"Example with Python","id":"example-with-python"},{"level":3,"title":"Example with PHP","id":"example-with-php"},{"level":2,"title":"Token Permissions","id":"token-permissions"},{"level":3,"title":"Available Scopes","id":"available-scopes"},{"level":3,"title":"Principle of Least Privilege","id":"principle-of-least-privilege"},{"level":2,"title":"Project Scope","id":"project-scope"},{"level":3,"title":"Selecting a project with an account-wide token","id":"selecting-a-project-with-an-account-wide-token"},{"level":3,"title":"Project-locked tokens","id":"project-locked-tokens"},{"level":2,"title":"Managing Tokens","id":"managing-tokens"},{"level":3,"title":"Viewing Active Tokens","id":"viewing-active-tokens"},{"level":3,"title":"Revoking Tokens","id":"revoking-tokens"},{"level":2,"title":"Security Best Practices","id":"security-best-practices"},{"level":3,"title":"Storage","id":"storage"},{"level":3,"title":"Rotation","id":"rotation"},{"level":3,"title":"Monitoring","id":"monitoring"},{"level":2,"title":"Authentication Errors","id":"authentication-errors"},{"level":3,"title":"401 Unauthorized","id":"401-unauthorized"},{"level":3,"title":"403 Forbidden","id":"403-forbidden"},{"level":2,"title":"Testing Authentication","id":"testing-authentication"},{"level":3,"title":"In the Interactive Docs","id":"in-the-interactive-docs"},{"level":3,"title":"Using cURL","id":"using-curl"},{"level":2,"title":"Next Steps","id":"next-steps"}],"format":"markdown","word_count":253,"content":"# API Authentication\n\nAll DanubeData API requests require authentication using Laravel Sanctum bearer tokens.\n\n## Creating an API Token\n\n### Step 1: Navigate to API Tokens\n\n1. Log in to your DanubeData account\n2. Click on your profile in the top right\n3. Select **API Tokens** from the menu\n\n### Step 2: Create a New Token\n\n1. Click the **Create New Token** button\n2. Enter a descriptive name for the token (e.g., \"Production Server\", \"CI/CD Pipeline\")\n3. Select the appropriate permissions for the token\n4. Choose the token's **project scope** — **This project only** (default) or **All my projects** (see [Project Scope](#project-scope))\n5. Click **Create**\n\n### Step 3: Save Your Token\n\n⚠️ **Important:** The token will only be shown once. Copy it immediately and store it securely.\n\n```\nToken: 1|7TEwyZaQXMXRVBZV9USjWNRbXAbPv9BrgMJSLDCk345196d2\n```\n\n## Using Your Token\n\n### In HTTP Headers\n\nInclude the token in the `Authorization` header with the `Bearer` prefix:\n\n```bash\ncurl -H \"Authorization: Bearer YOUR_TOKEN_HERE\" \\\n     https://danubedata.ro/api/v1/vps\n```\n\n### Example with cURL\n\n```bash\ncurl -X GET \\\n  'https://danubedata.ro/api/v1/vps' \\\n  -H 'Authorization: Bearer 1|7TEwyZaQXMXRVBZV9USjWNRbXAbPv9BrgMJSLDCk345196d2' \\\n  -H 'Accept: application/json'\n```\n\n### Example with JavaScript/Axios\n\n```javascript\nconst axios = require('axios');\n\nconst api = axios.create({\n  baseURL: 'https://danubedata.ro/api/v1',\n  headers: {\n    'Authorization': 'Bearer YOUR_TOKEN_HERE',\n    'Accept': 'application/json'\n  }\n});\n\n// Make a request\napi.get('/vps')\n  .then(response => console.log(response.data))\n  .catch(error => console.error(error));\n```\n\n### Example with Python\n\n```python\nimport requests\n\nheaders = {\n    'Authorization': 'Bearer YOUR_TOKEN_HERE',\n    'Accept': 'application/json'\n}\n\nresponse = requests.get(\n    'https://danubedata.ro/api/v1/vps',\n    headers=headers\n)\n\nprint(response.json())\n```\n\n### Example with PHP\n\n```php\n<?php\n\n$token = 'YOUR_TOKEN_HERE';\n$url = 'https://danubedata.ro/api/v1/vps';\n\n$ch = curl_init($url);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    'Authorization: Bearer ' . $token,\n    'Accept: application/json'\n]);\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\n\n$response = curl_exec($ch);\n$data = json_decode($response, true);\n\ncurl_close($ch);\nprint_r($data);\n```\n\n## Token Permissions\n\nTokens can have different permission scopes:\n\n### Available Scopes\n\n- `vps:read` - View VPS instances\n- `vps:write` - Create and update VPS instances\n- `vps:delete` - Delete VPS instances\n- `database:read` - View database instances\n- `database:write` - Manage database instances\n- `database:delete` - Delete database instances\n- `cache:read` - View cache instances\n- `cache:write` - Manage cache instances\n- `cache:delete` - Delete cache instances\n- `storage:read` - View storage buckets and access keys\n- `storage:write` - Create and manage storage buckets and access keys\n- `storage:delete` - Delete storage buckets and revoke access keys\n- `firewall:read` - View firewalls\n- `firewall:write` - Manage firewalls\n- `firewall:delete` - Delete firewalls\n- `ssh-key:read` - View SSH keys\n- `ssh-key:write` - Manage SSH keys\n- `ssh-key:delete` - Delete SSH keys\n- `snapshot:read` - View snapshots\n- `snapshot:write` - Create and restore snapshots\n- `snapshot:delete` - Delete snapshots\n- `webhook:read` - View webhook configuration\n- `webhook:write` - Manage webhook configuration\n- `serverless:read` - View serverless containers\n- `serverless:write` - Create and manage serverless containers\n- `serverless:delete` - Delete serverless containers\n- `static-site:read` - View static sites\n- `static-site:write` - Create and manage static sites\n- `static-site:delete` - Delete static sites\n\n### Principle of Least Privilege\n\nAlways create tokens with the minimum permissions required for their purpose:\n\n- **Read-only tokens** for monitoring and reporting\n- **Write tokens** only for automation that needs to create/modify resources\n- **Separate tokens** for different services/environments\n\n## Project Scope\n\nIn addition to permission scopes, every token is bound to a **project scope** that controls *which* of your projects it can touch. Choose the scope when you create the token:\n\n- **This project only** *(default for new tokens)* — the token is locked to the project you created it in and can never act on any other project. Ideal for a single integration or environment.\n- **All my projects** — an account-wide token that can act on any project you belong to.\n\nEach token in your list shows its scope at a glance, with the project name displayed on project-locked tokens.\n\n### Selecting a project with an account-wide token\n\nAn account-wide token acts on your **current project** by default. To target a specific project, send its ID in the `X-Team-Id` header:\n\n```bash\ncurl -H \"Authorization: Bearer YOUR_TOKEN\" \\\n     -H \"X-Team-Id: 42\" \\\n     https://danubedata.ro/api/v1/vps\n```\n\n### Project-locked tokens\n\nA project-locked token ignores any project other than the one it is bound to. If you send an `X-Team-Id` for a different project, the request is refused:\n\n```json\n{\n  \"message\": \"This token is scoped to a single project and cannot access the requested team.\",\n  \"error\": \"Forbidden\"\n}\n```\n\n> **Existing tokens keep working.** Tokens created before project scoping remain account-wide (**All my projects**) — nothing changes unless you choose to tighten them by creating a new project-locked token.\n\n## Managing Tokens\n\n### Viewing Active Tokens\n\nIn the API Tokens page, you can see:\n- Token name\n- Creation date\n- Last used date\n- Permissions\n\n### Revoking Tokens\n\nTo revoke a token:\n1. Go to the API Tokens page\n2. Find the token you want to revoke\n3. Click the **Delete** button\n4. Confirm the deletion\n\n⚠️ **Warning:** Revoking a token immediately invalidates it. Any services using that token will stop working.\n\n## Security Best Practices\n\n### Storage\n\n- **Never** commit tokens to version control\n- Store tokens in environment variables or secure vaults\n- Use different tokens for different environments (dev, staging, prod)\n\n### Rotation\n\n- Rotate tokens regularly (e.g., every 90 days)\n- Immediately revoke tokens when:\n  - An employee leaves\n  - A service is decommissioned\n  - A token may have been compromised\n\n### Monitoring\n\n- Check token usage regularly in the API Tokens page\n- Investigate any unexpected \"Last used\" dates\n- Set up alerts for unusual API activity\n\n## Authentication Errors\n\n### 401 Unauthorized\n\n**Error Response:**\n```json\n{\n  \"message\": \"Unauthenticated.\"\n}\n```\n\n**Causes:**\n- Missing `Authorization` header\n- Invalid token format\n- Revoked or expired token\n\n**Solution:**\n- Verify the token is included correctly\n- Check the token hasn't been revoked\n- Create a new token if needed\n\n### 403 Forbidden\n\n**Error Response:**\n```json\n{\n  \"message\": \"This action is unauthorized.\"\n}\n```\n\n**Causes:**\n- Token lacks required permissions\n- Trying to access resources from another team\n- Using a project-locked token against a different project (see [Project Scope](#project-scope))\n\n**Solution:**\n- Verify the token has the necessary scopes\n- Create a new token with appropriate permissions\n- Ensure you're accessing resources from your team\n- If the token is project-locked, use it only against its own project, or create an **All my projects** token\n\n## Testing Authentication\n\n### In the Interactive Docs\n\n1. Visit `/docs/api` in your browser\n2. Click the **Authorize** button (top right)\n3. Enter: `Bearer YOUR_TOKEN_HERE`\n4. Click **Authorize**\n5. Try any endpoint to verify it works\n\n### Using cURL\n\n```bash\n# Test with a simple endpoint\ncurl -H \"Authorization: Bearer YOUR_TOKEN\" \\\n     https://danubedata.ro/api/v1/vps\n\n# Should return your VPS instances or an empty array\n```\n\n## Next Steps\n\n- Visit `/docs/api` to explore all authenticated endpoints\n- Learn about rate limits\n- Set up webhooks for event notifications\n\n","prev":{"title":"API Overview","slug":"api-overview","url":"https://docs.danubedata.ro/api-overview","markdown_url":"https://docs.danubedata.ro/api-overview.md","json_url":"https://docs.danubedata.ro/api-overview.json"},"next":{"title":"Object Storage","slug":"api-storage","url":"https://docs.danubedata.ro/api-storage","markdown_url":"https://docs.danubedata.ro/api-storage.md","json_url":"https://docs.danubedata.ro/api-storage.json"},"index_url":"https://docs.danubedata.ro/index.json"}