# Get started

Learn about authentication, signature creation, error handling, and API key management.

## OpenAPI specification

The complete API schema is available as a single bundled file. It includes all endpoints, request and response structures, and field definitions. To integrate programmatically, download the specification in the preferred format, instead of parsing the rendered API reference:

div
a
svg
rect
path
YAML
    
a
svg
path
path
JSON
    
## Authentication and security

The Solidgate API v1 uses a signature-based authentication model. Each request must carry two headers that are computed from your Public and Secret key pair.

br
**API keys**

- **Format:** Public keys use the prefix `api_pk_`, secret keys use the prefix `api_sk_`.
- **Source:** Get both keys from the Solidgate Hub by navigating to **Developers** > **Channel details**.
- **Webhook keys** are a separate pair with the prefixes `wh_pk_` / `wh_sk_`, used exclusively for validating webhook payloads.


> Never expose your Secret key in client-side code or public repositories. Use it only in secure server-side environments.


br
**Required headers**

Every request must include two custom headers.

| Header | Description | Example |
|  --- | --- | --- |
| `merchant` | Your Public key, used to identify the requesting merchant. | `api_pk_7b197...ba108f842` |
| `signature` | HMAC-SHA512 signature that verifies the request source and data integrity. | `MjNiYFdSdjVj...hYmNiZDY` |


## Generate signature

The signature value is a Base64-encoded string of the hexadecimal representation of an HMAC-SHA512 hash, created using the Secret key.

br
**Signature data**

Concatenate the following string and use it as the HMAC input `publicKey` + `jsonString` + `publicKey`

> For **GET** requests that do not have a body, the signature data is simply `publicKey` + `publicKey`.


| Field | Description | Test data |
|  --- | --- | --- |
| `publicKey` | Your Public key. | `api_pk_8f8a8k8e8k8e8y8` |
| `jsonString` | Request body as a JSON string. | `{"amount": "100", "currency": "USD"}` |
| `secretKey` | Your Secret key. | `api_sk_8f8a8k8e8k8e8y8` |


br
**Steps**

ol
li
Pass the concatenated data and the Secret key to an HMAC-SHA512 function.
li
Get the hexadecimal representation of the hash.
li
Encode the hexadecimal string to Base64.
**Expected signature with the test data above**

```text
MjFkZGE3ZTZjODc0YjY5YTczOTlmOTBlYjk0MDY1NThiODJiZmE3ZTgxOGJjMWUxYjNkNTFjMDNjZmUzOGRlMTBhZGEzMmYxMGY3NTBlOTBlMGZkNDUwZTRiNmI5YTBiYTVmZWM5NzcxMjU3OWM0MGU5Mzg1NTljOTE1NTVlNzA=
```

**Code examples**

```php
class SignatureGenerator
{
        public static function generateSignature(string $publicKey, string $jsonString, string $secret_key): string
    {
        $text = $publicKey . $jsonString . $publicKey;
        $hashedBytes = hash_hmac('sha512', $text, $secret_key);
        return base64_encode($hashedBytes);
    }
    public static function main(array $args): void
    {
        $public_key = 'api_pk_8f8a8k8e8k8e8y8';
        $json_string = '{"amount": "100", "currency": "USD"}';
        $secret_key = 'api_sk_8f8a8k8e8k8e8y8';
        $signature = self::generateSignature($public_key, $json_string, $secret_key);
        echo $signature . "\n";
    }
}

SignatureGenerator::main([]);
```

```js
const crypto = require('crypto');

function generateSignature(publicKey, jsonString, secretKey) {
  const data = publicKey + jsonString + publicKey;
  const hmac = crypto.createHmac('sha512', secretKey);
  hmac.update(data);
  const hash = hmac.digest();
  const hexHash = hash.toString('hex');
  return Buffer.from(hexHash).toString('base64');
}

const publicKey = 'api_pk_8f8a8k8e8k8e8y8';
const jsonString = '{"amount": "100", "currency": "USD"}';
const secretKey = 'api_sk_8f8a8k8e8k8e8y8';

const signature = generateSignature(publicKey, jsonString, secretKey);
console.log(signature);
```

```python
# This code is intended for Python 3 or newer.
import hashlib
import hmac
import base64

def generateSignature(public_key, json_string, secret_key):
    data = public_key + json_string + public_key
    hmac_hash = hmac.new(secret_key.encode('utf-8'), data.encode('utf-8'), hashlib.sha512).digest()
    return base64.b64encode(hmac_hash.hex().encode('utf-8')).decode('utf-8')

public_key = "api_pk_8f8a8k8e8k8e8y8"
json_string = "{\"amount\": \"100\", \"currency\": \"USD\"}"
secret_key = "api_sk_8f8a8k8e8k8e8y8"

signature = generateSignature(public_key, json_string, secret_key)
print(signature)
```

## API structure and conventions

The v1 API uses domain-specific base URLs, except for endpoints for managing webhooks and files. Select the correct host for the resource you are working with.

br
**Base URLs**

| Host | Domain |
|  --- | --- |
| `https://pay.solidgate.com/api/v1` | **[Card payments](https://api-docs.solidgate.com/api/card-payments)** |
| `https://gate.solidgate.com/api/v1` | **[Alternative payment methods](https://api-docs.solidgate.com/api/alternative-payment-methods)** |
| `https://subscriptions.solidgate.com/api/v1` | **[Subscriptions](https://api-docs.solidgate.com/api/manage-subscriptions)** |
| `https://payment-page.solidgate.com/api/v1` | **[Payment Page](https://api-docs.solidgate.com/api/payment-page)** |
| `https://reports.solidgate.com/api/v1` | **[Reports](https://api-docs.solidgate.com/api/reports)** |
| `https://risks.solidgate.com/api/v1` | **[Fraud prevention](https://api-docs.solidgate.com/api/fraud-prevention)** |
| `https://api.solidgate.com/api/v1/` | **[Webhooks](https://api-docs.solidgate.com/api/manage-webhooks)** and **[Files](https://api-docs.solidgate.com/api/files-upload)** |


**Endpoint format**

Endpoints use the action name directly after the base URL. The HTTP method depends on the operation.

```text
{method} {host}/{action}
```

For example, to initiate a card payment:

```bash
POST https://pay.solidgate.com/api/v1/charge
```

br
**Data formatting**

- **Body:** JSON
- **Content-Type:** `application/json`


For the complete list of endpoints, methods, and parameters, see the Solidgate API reference.

> Using an action with the wrong base URL results in a **Blocked by WAF** error. For example, the endpoint `/subscription/cancel-by-customer` must be called on `subscriptions.solidgate.com`, not `pay.solidgate.com`.


## Error handling

The API uses standard HTTP status codes. All errors return a consistent JSON structure.

| Status | Category | Description |
|  --- | --- | --- |
| 400 | Validation | Malformed JSON or invalid field constraints |
| 401 | Unauthorized | Invalid or missing merchant/signature headers |
| 403 | Access denied | Missing required permissions |
| 404 | Not found | Resource or endpoint does not exist |
| 422 | State error | Request conflicts with current system state |
| 429 | Rate limit | Request quota exhausted |
| 500 | Internal | Server-side failure |


br
**Error response structure**

```json
{
  "error": {
    "code": "3.02",
    "messages": [
      "The user's card balance has insufficient funds."
    ],
    "recommended_message_for_user": "Please try a different payment method."
  }
}
```

For the full list of error codes, see the error codes reference.

## Rate limits

Rate limiting controls the frequency at which requests are made to API endpoints within specific time periods.

It helps protect against service overload while ensuring consistent performance for all clients. Exceeding limits results in a `429 Too many requests` error response.

br
**API usage limits**

Solidgate returns the `429` error response when necessary to protect legitimate merchant traffic.

Rate limits differ by endpoint based on operational and reliability needs. The Solidgate team continuously monitors system performance and may adjust these limits as needed to maintain optimal service quality.

For endpoint-specific rate limit information, visit the **Developers** section in the Solidgate Hub, which is updated as changes occur.

br
**Handle rate limits**

You can handle rate limiting by monitoring for the `429 Too many requests` error response. Effective handling combines retries and overall request flow control.

A widely used approach for handling rate limit error responses is implementing exponential backoff with jitter. This method retries requests using short initial delays that increase after each failure. Introducing randomization, or jitter, helps avoid conflicts caused by multiple clients retrying simultaneously.

While retries are useful, a significant improvement comes from regulating request flow across the entire application. The token bucket is standard practice for this purpose. It allows short bursts of requests while enforcing an average request rate over time, reducing traffic spikes and improving overall stability.

## Webhook validation

Solidgate signs outgoing webhook payloads with the same HMAC-SHA512 method used for API requests. Use the dedicated Webhook keys (`wh_pk_` / `wh_sk_`) to verify inbound webhooks.

1. Extract the `merchant` and `signature` values from the webhook headers.
2. Reconstruct the expected signature using the webhook Public key, the raw JSON body, and the webhook Secret key.
3. Compare the computed signature to the one in the header. Reject the request if they do not match.


## Outgoing request IPs

Specific IP addresses are used for outbound requests from Solidgate to your systems (for example, webhooks). Allow traffic from these IPs in your firewall or security configuration to ensure uninterrupted service.

| IP addresses |
|  --- |
| `3.74.184.6` / `3.121.136.242` |
| `18.156.25.95` / `18.157.254.13` / `18.157.119.243` / `18.184.24.146` / `18.192.168.222` / `18.195.90.222` |
| `35.157.172.91` / `35.165.202.104` |
| `44.224.79.149` |
| `52.10.37.135` / `52.88.195.65` |


## Handle WAF errors

The **Blocked by WAF** error indicates that a Web Application Firewall (WAF) has prevented your request due to a policy violation. The most common cause is sending a request to the wrong base URL.

1. Confirm that the full URL matches a valid endpoint in the Solidgate API reference.
2. Ensure that the endpoint corresponds to the correct base URL for that domain.


For example, if you attempt to cancel a subscription using the endpoint `/subscription/cancel-by-customer` at the base URL `pay.solidgate.com/api/v1`, you receive a **Blocked by WAF** error. The correct base URL for subscription actions is `subscriptions.solidgate.com/api/v1`.

## Backward compatibility

Changes to the Solidgate APIs are aimed at minimizing the impact on existing integrations. However, depending on the type of change, actions may be required.

> Any API change that requires client-side adjustments will be communicated by the Solidgate team. These changes include preparation time and clear guidance.
When a field or feature is marked as **deprecated** and a **deprecation notice** is added to the changelog, it serves as an early notice. Deprecated fields or features are not removed immediately.


br
Breaking changes can impact existing integrations and require adjustments. These are marked with a **breaking changes** badge in the changelog and include:

| Category | Change |
|  --- | --- |
| **Operation removal** | Removing an API operation. |
| **Request** | Remove or rename a field, make optional fields required, remove `oneOf`. |
| **Response** | Remove or rename a field, change HTTP status code, remove `oneOf`. |
| **Type changes** | Change request or response data types. |
| **HTTP headers** | Add required headers or remove existing ones. |
| **Enum updates** | Remove enum values. |
| **Errors** | Change existing error codes. |
| **Validation rules** | Add stricter or new rules. |
| **Authentication and authorization** | Change requirements. |


Non-breaking changes modifications do not affect existing integrations and ensure backward compatibility:

| Category | Change |
|  --- | --- |
| **Request** | Add new optional fields, change required fields to optional. |
| **Response** | Add new optional fields, change optional fields to required. |
| **HTTP headers** | Add new optional headers, change header case. |
| **Field length** | Expand maximum length. |
| **Identifier format** | Change prefixes or formatting. |
| **Webhook events** | Add new opt-in event types. |
| **Webhook schema** | Add new fields. |
| **Rate limiting** | Changes communicated at least one month in advance. |


For help, contact us.