# Authentication

> Send a ReportingCloud-APIKey or Basic Authorization header with every Web API request from curl, .NET, PHP, Java or Ruby, and read 403 and 500 answers.

- **Product:** ReportingCloud
- **Section:** Documentation
- **Kind:** Topic
- **Path:** ReportingCloud > Document Processing > Authentication
- **2022 words**
- **Web URL:** https://docs.textcontrol.com/reporting-cloud/document-processing/authentication/
- **LLMs URL:** https://docs.textcontrol.com/reporting-cloud/document-processing/authentication/llms.txt
- **LLMs-Full URL:** https://docs.textcontrol.com/reporting-cloud/document-processing/authentication/llms-full.txt

---

The `Authorization` header of a request tells the ReportingCloud Web API which account the request acts for. It holds either an API key or the user name and password of the account. There is no token to request first and no session to open: the header travels with each call, whether curl, an SDK or your own HTTP client sends it. Read on for the two header formats, how each SDK builds them and what the service answers when the credentials are missing or wrong.

### How Authentication Works

The Web API accepts two kinds of credentials, and each request carries exactly one of them:

| Method | Header | Built from |
|---|---|---|
| API key | `Authorization: ReportingCloud-APIKey <key>` | An API key of your account, unchanged |
| Basic | `Authorization: Basic <credentials>` | The user name, which is the email address of the account, and the password, joined by a colon and Base64-encoded |

Text Control recommends API keys over Basic authentication; [API Keys](https://docs.textcontrol.com/reporting-cloud/installation/api-keys/#why-use-api-keys) gives the reasons and shows how to create and delete keys. A key opens your account, its data and its templates to whoever holds it, and every document they create counts against your quota, so treat it like a password and keep it out of source code and repositories.

All endpoints are below `https://api.reporting.cloud/v1/`, and the Web API answers on HTTPS only, so the credentials are always sent encrypted. A request to `http://api.reporting.cloud` gets no answer.

### Authenticate With an API Key

Keep the key in an environment variable and send it in the header. The following request asks for the number of templates in your template storage, which counts against none of the quotas:

```bash
export REPORTINGCLOUD_API_KEY="<API key>"

curl "https://api.reporting.cloud/v1/templates/count" \
  -H "Authorization: ReportingCloud-APIKey $REPORTINGCLOUD_API_KEY"
```

The response body is the number, for example `3`. What the request shows:

- **The header value** is the word `ReportingCloud-APIKey`, a space and the key. The word and the key are matched regardless of case, so `reportingcloud-apikey` works as well.
- **The same header works for every endpoint**, with GET, POST, PUT and DELETE requests alike.
- **Endpoints that take a JSON body** also need `-H "Content-Type: application/json"`, as the samples on the following pages show.

### Authenticate With User Name and Password

Basic authentication sends the credentials of the account itself. curl builds the header from `--user`:

```bash
curl "https://api.reporting.cloud/v1/templates/count" \
  --user "<email address>:<password>"
```

Another HTTP client needs the header written out:

1. Join the user name and the password with a colon, for example `user@example.com:password`.
2. Encode the string as Base64 on one line, without line breaks. In a shell, `printf '%s' 'user@example.com:password' | base64 -w 0` does it.
3. Put the word `Basic` and a space in front of the result:

    ```text
    Authorization: Basic dXNlckBleGFtcGxlLmNvbTpwYXNzd29yZA==
    ```

The word `Basic` and the user name are matched regardless of case.

Basic authentication sends your password with every request, and code that uses it stops working when the password changes. Use an API key wherever your client supports one.

### Authenticate With the SDKs

Each SDK takes the credentials once, when you create its `ReportingCloud` object, and adds the header to every request it sends:

| SDK | With an API key | With user name and password |
|---|---|---|
| .NET, package `TXTextControl.ReportingCloud` | `new ReportingCloud(apiKey)` | `new ReportingCloud(username, password)` |
| PHP, package `textcontrol/textcontrol-reportingcloud` | `new ReportingCloud(['api_key' => $apiKey])` | The options `'username'` and `'password'`, marked as deprecated |
| Java | Not supported | `new ReportingCloud(username, password)` |
| Ruby | Not supported | `ReportingCloud.new(username, password)` |

The Java and Ruby SDKs always send a Basic header. Their API key methods, such as `createAPIKey` and `create_api_key`, manage the keys of the account but don't use them. [SDKs](https://docs.textcontrol.com/reporting-cloud/sdks/llms-full.txt) compares the four.

The following .NET console application authenticates with an API key and prints the number of templates in the storage:

```csharp
using TXTextControl.ReportingCloud;

// Read the API key from an environment variable instead of the source code
string apiKey = Environment.GetEnvironmentVariable("REPORTINGCLOUD_API_KEY")
    ?? throw new InvalidOperationException("Set REPORTINGCLOUD_API_KEY first.");

// Every request of this instance sends "Authorization: ReportingCloud-APIKey <key>"
ReportingCloud rc = new ReportingCloud(apiKey);

int count = rc.GetTemplateCount();
Console.WriteLine($"Templates in the storage: {count}");
```

The code works as follows:

- The `ReportingCloud` constructor with one string takes an API key. Further constructors take the base URL of the Web API as a `Uri` as their last argument, `ReportingCloud(apiKey, webApiBaseUrl)` and `ReportingCloud(username, password, webApiBaseUrl)`; without it, the SDK uses `https://api.reporting.cloud`.
- When an API key is set, the SDK sends it. Otherwise, it builds a Basic header from the `Username` and `Password` properties.
- `GetTemplateCount` sends `GET /v1/templates/count` and returns the number.

Install the package with `dotnet add package TXTextControl.ReportingCloud`, as [Installing an SDK](https://docs.textcontrol.com/reporting-cloud/installation/sdks/llms-full.txt) shows.

In PHP, the key goes into the `'api_key'` option of the constructor, `new ReportingCloud(['api_key' => (string) getenv('REPORTINGCLOUD_API_KEY')])`, or into `setApiKey()` of an existing object before its first request: the SDK builds the header once, for the first request, and ignores a key set later. Without an API key and without a user name and password, the PHP SDK sends nothing: its first request throws an `InvalidArgumentException` with the message "Either the API key, or username and password must be set for authorization".

### Call the Web API From a Browser

The Web API allows cross-origin requests from any origin: it answers with `Access-Control-Allow-Origin: *` and accepts the `Authorization` and `Content-Type` headers in them. A script in a web page could therefore call it, but the key or password it sends would be visible to every visitor of the page. Send the requests from your server and pass only the results to the browser, as [Data Security and Privacy](https://docs.textcontrol.com/reporting-cloud/overview/security/#credentials-and-api-keys) explains.

### When Authentication Fails

What a client sees depends on what is wrong:

- **Credentials that aren't authorized.** An unknown or deleted API key, or a wrong user name or password, gets `403 Forbidden` with the plain-text body `Invalid username/password combination or invalid APIKey`. The endpoints with a quota answer `403` as well when the quota is exceeded.
- **No valid `Authorization` header.** A request without credentials, with an empty `Authorization` header or with one that is not the authorization method, a space and the credentials, such as `ReportingCloud-APIKey:` followed by the key, gets `500 Internal Server Error` instead, with this body:

    ```json
    {"Message":"An error has occurred."}
    ```
- **In the SDKs.** The .NET SDK throws an `ArgumentException` whose message is the response body. The PHP SDK throws a `TextControl\ReportingCloud\Exception\RuntimeException` whose code is the HTTP status.

[Troubleshooting: Authentication](https://docs.textcontrol.com/reporting-cloud/troubleshooting/authentication/llms-full.txt) lists the causes and their fixes, and [Errors and Status Codes](https://docs.textcontrol.com/reporting-cloud/document-processing/errors/llms-full.txt) explains every answer of the Web API.

### Next Steps

- [API Keys](https://docs.textcontrol.com/reporting-cloud/installation/api-keys/llms-full.txt): create the key that your requests send.
- [Converting Documents](https://docs.textcontrol.com/reporting-cloud/document-processing/converting/llms-full.txt): send a first document with the key and get it back as PDF.
- [Installing an SDK](https://docs.textcontrol.com/reporting-cloud/installation/sdks/llms-full.txt): add the .NET, PHP, Java or Ruby SDK to a project.
- [Errors and Status Codes](https://docs.textcontrol.com/reporting-cloud/document-processing/errors/llms-full.txt): what a `403` or `500` answer means.

---

## Nearby

- **Previous:** [Document Processing](https://docs.textcontrol.com/reporting-cloud/document-processing/llms-full.txt)
- **Next:** [Converting Documents](https://docs.textcontrol.com/reporting-cloud/document-processing/converting/llms-full.txt)
