# Authentication

{% hint style="info" %}
All requests to the Discloud API must include an **API Token** in the `api-token` header.

If you don't have a token yet, generate or retrieve it in your Discloud dashboard. (Replace this note with the exact dashboard link or a screenshot.)
{% endhint %}

***

## ⚙️ How It Works

{% stepper %}
{% step %}
You generate a unique [token](https://docs.discloud.com/en/faq/general-questions/how-can-i-get-my-discloud-api-token) linked to your account.
{% endstep %}

{% step %}
For every HTTP request include the header: `api-token: YOUR_TOKEN_HERE`.
{% endstep %}

{% step %}
The token authenticates and authorizes actions on behalf of your account (never share it).
{% endstep %}

{% step %}
Use the `/user` endpoint to quickly validate the token.
{% endstep %}
{% endstepper %}

***

## 📤 Sending the Token

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X GET \
  -H "api-token: $DISCLOUD_TOKEN" \
  https://api.discloud.app/v2/user
```

{% endtab %}

{% tab title="Node.js (fetch)" %}

```javascript
import fetch from "node-fetch";

async function getCurrentUser() {
  const res = await fetch("https://api.discloud.app/v2/user", {
    headers: { "api-token": process.env.DISCLOUD_TOKEN },
  });

  if (!res.ok) {
    console.error("Request failed:", res.status, await res.text());
    return;
  }
  const data = await res.json();
  console.log(data);
}
```

{% endtab %}

{% tab title="Node.js (discloud.app SDK)" %}

```javascript
// Install first: npm i discloud.app
const { discloud } = require("discloud.app");

async function validateToken() {
  try {
    const user = await discloud.login("DISCLOUD_API_TOKEN");
    console.log("Authenticated user:", user);
  } catch (e) {
    console.error("Invalid token or network error:", e.message);
  }
}
```

{% endtab %}
{% endtabs %}

***

## 🛡 Securing the Token

{% hint style="warning" %}
Never commit your token (e.g. to Git). Store it in environment variables ([`.env`](https://docs.discloud.com/en/faq/general-questions/.env-file), CI/CD secrets, etc.).
{% endhint %}

📌 Best practices:

* Use environment variables instead of hard‑coding.
* Rotate the token periodically (e.g. every 90 days).
* Revoke and regenerate immediately if you suspect exposure.
* Restrict who can access infrastructure where the variable is stored.

***

## ⚡ Quick Token Verification

Call `/user` right after setting the environment variable. If you get HTTP 200 with user data, authentication is working.

{% hint style="info" %}
You can also update the user locale (e.g. `en-US`) through `/locale/{locale}` to validate another authenticated route.
{% endhint %}

***

## 📚 Related Endpoints References

The operations below require the `api-token` header:

## Get current user information

> Returns information about the authenticated user

```json
{"openapi":"3.0.4","info":{"title":"Discloud API","version":"2.0.0"},"tags":[{"name":"User","description":"Operations about users"}],"servers":[{"url":"https://api.discloud.app/v2","description":"API Server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"api-token"}},"schemas":{"UserResponse":{"type":"object","properties":{"status":{"type":"string"},"message":{"type":"string"},"user":{"$ref":"#/components/schemas/User"}}},"User":{"type":"object","properties":{"userID":{"type":"string","description":"The unique identifier of the user"},"totalRamMb":{"type":"integer","description":"Total RAM allocated to the user (in MB)"},"ramUsedMb":{"type":"integer","description":"RAM currently being used by the user (in MB)"},"subdomains":{"type":"array","items":{"type":"string"},"description":"List of subdomains owned by the user"},"customdomains":{"type":"array","items":{"type":"string"},"description":"List of custom domains owned by the user"},"apps":{"type":"array","items":{"type":"string"},"description":"List of application IDs owned by the user"},"plan":{"type":"string","description":"The subscription plan of the user"},"locale":{"type":"string","description":"The language/locale"},"lastDataLeft":{"type":"object","properties":{"days":{"type":"integer","description":"Days remaining in the current plan"},"hours":{"type":"integer","description":"Hours remaining in the current plan"},"minutes":{"type":"integer","description":"Minutes remaining in the current plan"},"seconds":{"type":"integer","description":"Seconds remaining in the current plan"}},"description":"Time remaining in the current plan"},"planDataEnd":{"type":"string","format":"date-time","description":"End date of the current plan"}}},"Error":{"type":"object","properties":{"code":{"type":"integer"},"message":{"type":"string"}}}}},"paths":{"/user":{"get":{"tags":["User"],"summary":"Get current user information","description":"Returns information about the authenticated user","operationId":"getCurrentUser","responses":{"200":{"description":"Successful operation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}},"401":{"description":"Authentication error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}
```
