Authentication
Every request to the ReportingCloud Web API carries an Authorization header: an API key as ReportingCloud-APIKey <key>, or the user name and password of the account as Basic <Base64 string>. When the service can't use that header, it doesn't process the request: a request without the header gets status 500 with a message that names no cause, and a key or password the service doesn't know gets 403 Forbidden with a short plain-text message. Start with the test below, then find the response or message you see among the problems that follow.
Test the Credentials on Their Own
A 403 response from a document request doesn't always mean that the credentials are wrong: the Web API also returns it when a quota is used up or too many requests run at the same time. To rule the credentials in or out, send them to GET /v1/account/settings. The endpoint returns the quotas of the account and creates no document:
curl "Authorization: ReportingCloud-APIKey $REPORTINGCLOUD_API_KEY" \
https://api.reporting.cloud/v1/account/settings
The option -i prints the status line and the response headers before the body. The status tells you where to go next:
- 200 with a JSON object: the service accepts the credentials. When another request returns 403, the cause is a quota or the limit of concurrent requests, as Quotas and Limits describes.
- 403 with
Invalid username/password combination or invalid APIKey: the service doesn't accept the credentials. See Requests Return 403 Forbidden. - 500 with
{"Message":"An error has occurred."}: see A Request Without Credentials Returns 500.
See What the Request Sends
Before you change the credentials, check that the request carries them. The option -v of curl prints every request header on a line that starts with >:
curl "Authorization: ReportingCloud-APIKey $REPORTINGCLOUD_API_KEY" \
https://api.reporting.cloud/v1/account/settings
Find the line that starts with
> Authorization:. It holdsReportingCloud-APIKey, one space and the key, orBasic, one space and the encoded credentials.If the line ends after
ReportingCloud-APIKey, the variable is empty in the shell that ran curl, and the service answers 403.printenv REPORTINGCLOUD_API_KEYprints the key, or nothing when the variable isn't set.Set the variable and send the request again:
export REPORTINGCLOUD_API_KEY='<API key>'When your application sends the request, inspect its headers the same way, for example in a log of the HTTP client. A request without an
Authorizationheader has no credentials; see the next section.
The output of -v contains the key in plain text. Keep it out of tickets, chat messages and logs: anybody who has the key can use the quota of your account.
A Request Without Credentials Returns 500
A request returns status 500 with a short JSON body that doesn't name a cause:
HTTP/2 500
content-type: application/json; charset=utf-8
{"Message":"An error has occurred."}
The request reached the Web API without an Authorization header, with an empty one, or with one that isn't the authorization method, a space and the credentials, such as ReportingCloud-APIKey: followed by the key. A request without credentials gets 500, not 403; see Requests Without Credentials.
- Add the header to every request:
-H "Authorization: ReportingCloud-APIKey $REPORTINGCLOUD_API_KEY"with curl. The SDKs build it from the credentials you pass to their constructor; Authentication shows both header forms and the SDK calls. - Check with
curl -vthat the header is sent, as See What the Request Sends describes. - Send the request again. If it now returns 403, the header arrives but the credentials aren't accepted.
- If the header reads
ReportingCloud-APIKey <key>orBasic <Base64 string>and the request still returns 500, check the request body, which Errors and Status Codes lists among the causes of a 500, and look for a reported incident on the status page, as Check the Service Status describes.
Requests Return 403 Forbidden
Every request, GET /v1/account/settings included, returns 403 with a plain-text body:
HTTP/2 403
content-type: text/plain; charset=utf-8
Invalid username/password combination or invalid APIKey
The Authorization header arrived, but the service doesn't know the key or the user name and password in it. Forbidden describes the response. The common causes are:
- The header isn't in the expected form. The value is the method name
ReportingCloud-APIKey, one space and the key. A key in quotes, another method name or an empty key gets the same 403. - The key is incomplete. API keys are random strings of more than 40 characters. A key that lost characters, or gained a line break or a space when it was copied, isn't the same key.
- The key was deleted. A key removed with Delete Key under Manage Account in the portal, or with DELETE /v1/account/apikey, no longer authorizes requests.
- The .NET SDK got no key. When the environment variable isn't set,
Environment.GetEnvironmentVariablereturnsnull. TheReportingCloudconstructor accepts it, and the SDK then sends Basic authentication with an empty user name and password,Authorization: Basic Og==, which gets the same 403. - The Basic credentials don't match. See the next section.
To fix it:
- Sign in to the portal, open Manage Account and compare your key with the list of API keys.
- If the key isn't in the list, click Create Key and store the new key where your application reads it, for example in the environment variable
REPORTINGCLOUD_API_KEY. An account has up to 10 API keys; API Keys describes how to manage them. - Send the test request of Test the Credentials on Their Own again.
Basic Authentication Fails
A request with Authorization: Basic ... returns 403 with Invalid username/password combination or invalid APIKey, while the same account works with an API key or used to work with the same code.
Basic authentication sends the user name and password of the ReportingCloud account, so it fails in these situations:
- The password has changed. Every application that still sends the old password is refused. API keys don't depend on the password.
- The credentials are encoded incorrectly. The value after
Basicis the stringusername:passwordencoded with Base64 on a single line, as Authentication shows. With thebase64command of GNU coreutils, two slips change the result:echoadds a line break that is encoded with the credentials, andbase64wraps its output after 76 characters. - The .NET SDK changes characters outside ASCII. It encodes the user name and password as ASCII, so it sends every other character, such as
äor€, as?, and the credentials no longer match.
The difference is visible in the result:
# Encodes the line break that echo adds: dXNlcjpwYXNzCg==
echo 'user:pass' | base64
# Encodes only the credentials, on one line: dXNlcjpwYXNz
printf '%s' 'user:pass' | base64 0
To fix it:
- Let curl build the header: the option
-u 'username:password'sendsAuthorization: Basicwith the correctly encoded credentials. - When you build the header yourself, encode the credentials without a line break and without wrapping, as the second command above does.
- After a password change, update the credentials in every application that uses Basic authentication. Better, replace them with an API key, as API Keys describes. With the .NET SDK and a password that has characters outside ASCII, an API key is the fix.
The PHP SDK Reports Missing Credentials
A PHP script that uses the SDK textcontrol/textcontrol-reportingcloud stops before it sends a request, with this message of TextControl\ReportingCloud\Exception\InvalidArgumentException:
Either the API key, or username and password must be set for authorization
Or it stops when it creates the ReportingCloud object, with a TypeError whose message begins:
TextControl\ReportingCloud\AbstractReportingCloud::setApiKey(): Argument #1 ($apiKey) must be of type string, false given
The SDK builds the Authorization header itself. It throws the first exception when neither an API key nor both a user name and a password are set, for example because the key is an empty string. The TypeError appears when the variable isn't set at all: getenv() then returns false, and the SDK accepts only a string as api_key. Both messages were reproduced with version 4.0.5 of the SDK.
Set the environment variable
REPORTINGCLOUD_API_KEYfor the process that runs PHP, not only in your shell.Check the value before you create the object, so that a missing key gives a clear message:
declare(strict_types=1); require_once __DIR__ . '/vendor/autoload.php'; use TextControl\ReportingCloud\ReportingCloud; $apiKey = getenv('REPORTINGCLOUD_API_KEY'); if (false === $apiKey || '' === $apiKey) { exit('Set the environment variable REPORTINGCLOUD_API_KEY.' . PHP_EOL); } $reportingCloud = new ReportingCloud([ 'api_key' => $apiKey, ]);Run the script again. Once the key is set, a refused key returns 403 like any other client, as Requests Return 403 Forbidden describes.