# API Key Authentication

Generate and use API keys for direct company access.

## Overview

API keys provide a simple authentication method for merchants to integrate their own systems with Cheqi. Each key represents exactly one company. It can access that company's direct store locations, but it cannot act for a parent, child, sibling, or unrelated company.

**Key Benefits:**

- **Simple to use** - No token management or OAuth flows required
- **Direct integration** - Perfect for companies issuing receipts through their own systems
- **Multi-store access** - Manage all stores that belong directly to the key's company
- **No external access** - Cannot perform actions for other organizations


**Perfect for:**

- Merchants who own their POS system and want direct integration
- E-commerce businesses managing their own webshop platform
- **Retail chains** whose locations all use the same legal company
- Companies that need straightforward authentication without OAuth complexity


For a corporate group or franchise with several Cheqi companies, use one API key per legal company or use [OAuth multi-company authorization](/authentication/oauth#multi-company-support).

Merchant Ownership Required
API keys are only available for merchants who own and control their point-of-sale system or e-commerce platform. If you're using a third-party POS provider or webshop platform, you'll need to use [OAuth authentication](/authentication/oauth) instead.

Exact Company Context
An API key never inherits receipt authority from a parent-company relationship. To issue for a child company, authenticate as that child company.

Keep API Keys Secret
API keys provide broad access to the authenticated company and its directly
owned stores. Never commit them to version control or expose them in a client
application.

## Generating an API Key

### Via the Cheqi Mobile App

1. Open the **Cheqi app** on your device
2. Navigate to **Profile** → **Company Profile**
3. Select **Developer Tools** → **API Keys**
4. Tap **Create New API Key**
5. Enter a **descriptive name** (e.g., "Production POS System")
6. **Copy the key immediately** - it will only be shown once


One-Time Display
The API key is displayed only once during creation. Store it securely in your application's configuration.

### Key Format

API keys follow this format:

```
sk_1234567890abcdef1234567890abcdef
```

- **Prefix:** `sk_` (Cheqi Secret Key)
- **Key:** 32-character alphanumeric string


## Using API Keys

### Authentication Header

Include your API key in the `Authorization` header with the `Bearer` scheme:

```bash
curl https://api.cheqi.io/recipient/resolve \
  -H "Authorization: Bearer sk_1234567890abcdef1234567890abcdef" \
  -H "Content-Type: application/json" \
  -d '{...}'
```

### SDK Configuration

Configure your SDK with the API key:

**HTTP Example:**

```bash
# Direct API integrations use the split flow:
# 1. POST /recipient/resolve
# 2. Encrypt the definitive receipt payload locally for every returned device
# 3. POST /receipt/encrypted, or use the explicitly selected fallback route
curl https://api.cheqi.io/recipient/resolve \
  -H "Authorization: Bearer sk_1234567890abcdef1234567890abcdef" \
  -H "Content-Type: application/json" \
  -d '{...}'
```

**Conceptual SDK Usage:**

```java
// Initialize SDK with API key
CheqiSDK sdk = CheqiSDK.builder()
    .apiEndpoint(Environment.PRODUCTION)
    .apiKey("sk_1234567890abcdef1234567890abcdef")
    .build();

// Use SDK to send receipts
ReceiptResult result = sdk.getReceiptService()
    .issueReceipt(identificationDetails, receiptPayload);
```

See the [Java SDK](/sdk/java) and [JavaScript SDK](/sdk/javascript) guides for implementation details. For another language, see [SDK Availability](/sdk/overview).

### Secure Storage

Never Hardcode API Keys
**Never hardcode API keys** in your source code or commit them to version control. Always use secure configuration management.

**Recommended approaches:**

- Environment variables
- Secure configuration files (excluded from version control)
- Secret management services (AWS Secrets Manager, Azure Key Vault, HashiCorp Vault)
- Encrypted configuration stores


## API Key Scopes

API keys automatically have the following access for **their exact company context**:

- ✅ **Write Receipts** - Send receipts as the authenticated company, optionally identifying one of its stores
- ✅ **Read Receipts** - Query receipt data for the authenticated company
- ✅ **Write Stores** - Manage stores owned directly by the authenticated company
- ✅ **Read Stores** - Access store location data
- ✅ **Company Data** - Access company information
- ❌ **Related Companies** - Cannot act for parent, child, or sibling companies
- ❌ **Other Organizations** - Cannot act for unrelated companies


Company and Store Boundary
The company in the API key is always the legal receipt issuer. A `storeId` adds the physical or operational location; it never changes the issuer.

### Multi-Store Example

If one retail company operates several locations, create those locations as
stores under that company and use the company's API key during encrypted
submission:

```json
{
  "matchId": "match_opaque",
  "storeId": "amsterdam-store-uuid",
  "deviceDeliveries": [
    {
      "deviceRecipientId": "rcpt_temporary",
      "encryptedContent": "base64-ciphertext",
      "encryptedAesKey": "base64-wrapped-key"
    }
  ]
}
```

This succeeds only when `amsterdam-store-uuid` belongs directly to the company
represented by the API key. Using a parent-company key with a child company's
store returns `403 Forbidden`. The deprecated `childCompanyId` field cannot
change the legal issuer.

See [Companies, Child Companies, and Stores](/companies/structure) for corporate-group and franchise examples.

## Managing API Keys

### Listing Active Keys

View all API keys for your company in the Cheqi app:

**Profile** → **Company Profile** → **Developer Tools** → **API Keys**

Each key shows:

- **Name** - Descriptive label you provided
- **Key Prefix** - First 8 characters (e.g., `sk_12345...`)
- **Created** - When the key was generated
- **Last Used** - Most recent API call timestamp
- **Status** - Active or Revoked


### Revoking API Keys

Revoke a key immediately if:

- ❌ The key was accidentally exposed
- ❌ An employee with access left the company
- ❌ You're rotating keys for security
- ❌ The integration is no longer in use


**To revoke:**

1. Go to **API Keys** in the app
2. Select the key to revoke
3. Tap **Revoke Key**
4. Confirm the action


Irreversible Action
Revoking a key is immediate and irreversible. All API calls using that key will fail with `401 Unauthorized`.

## Best Practices

### Security

#### Never Hardcode API Keys

```java
// ❌ BAD - Hardcoded key
CheqiSDK sdk = CheqiSDK.builder()
    .apiKey("sk_1234567890abcdef1234567890abcdef")
    .build();

// ✅ GOOD - Environment variable
CheqiSDK sdk = CheqiSDK.builder()
    .apiKey(System.getenv("CHEQI_API_KEY"))
    .build();
```

#### Use Different Keys for Different Environments

```bash
# Development
CHEQI_API_KEY=sk_dev1234567890abcdef

# Staging
CHEQI_API_KEY=sk_staging1234567890abcdef

# Production
CHEQI_API_KEY=sk_prod1234567890abcdef
```

#### Rotate Keys Regularly

1. Generate a new API key
2. Update your application configuration
3. Deploy the update
4. Verify the new key works
5. Revoke the old key


#### Monitor Key Usage

Regularly check the **Last Used** timestamp in the app to detect:

- Unused keys that should be revoked
- Unexpected usage patterns
- Keys that may have been compromised


### Key Naming

Use descriptive names that indicate:

- **Environment:** Production, Staging, Development
- **System:** POS System, Webshop, Mobile App
- **Location:** Store 1, Store 2, Warehouse


**Examples:**

- `Production POS - Store Amsterdam`
- `Production POS - Northstar Retail NL B.V.`
- `Development Testing Key`


## Error Handling

### Common Errors

| Status Code | Error | Solution |
|  --- | --- | --- |
| `401` | Invalid API key | Verify the key is correct and not revoked |
| `401` | API key revoked | Generate a new key and update your configuration |
| `403` | Insufficient permissions | API keys have full company access - check company ownership |
| `429` | Rate limit exceeded | Implement exponential backoff and retry logic |


### Example Error Response

```json
{
  "error": "unauthorized",
  "message": "Invalid or revoked API key",
  "timestamp": "2024-01-13T21:00:00Z"
}
```

## Testing

### Sandbox Environment

Use the [Cheqi Sandbox](/sandbox/getting-started) to test your API key integration. Create an account at [sandbox.portal.cheqi.io](https://sandbox.portal.cheqi.io), register a company, and generate an API key.

```bash
# Sandbox environment
CHEQI_API_BASE_URL=https://sandbox.api.cheqi.io
CHEQI_API_KEY=sk_your_sandbox_key
```

**SDK Configuration:**

```java
CheqiSDK sdk = CheqiSDK.builder()
    .customApiEndpoint("https://sandbox.api.cheqi.io")
    .apiKey(System.getenv("CHEQI_API_KEY"))
    .build();
```

The sandbox has pre-configured test customers with known card PARs, so you can test the full receipt flow end-to-end.

### Verify API Key

Test your API key with a simple request:

```bash
curl https://sandbox.api.cheqi.io/company/{companyId}/public \
  -H "Authorization: Bearer sk_your_sandbox_key"
```

Expected response:

```json
{
  "id": "uuid",
  "companyName": "Your Company Name",
  "companyEmail": "info@yourcompany.com"
}
```

## Next Steps

- [Receipt Flow](/receipts/overview) - Learn how to send receipts using your API key
- [Java SDK](/sdk/java) - Java SDK implementation guide
- [JavaScript SDK](/sdk/javascript) - JavaScript and TypeScript implementation guide
- [SDK Availability](/sdk/overview) - Request another SDK language