---
title: "Authentication"
description: "Authenticate Inttegro API requests with an opaque bearer key."
canonical: "https://studio.inttegro.com/api/authentication"
format: inttegro-machine-docs/v1
language: "PHP"
sdk_version: "v12.0.0"
reader_profile: optional
reader_manifest: "https://studio.inttegro.com/machine/php/readers/index.json"
reader_identification: "Optional: declare your client only if known and your current-session capabilities; use reader_manifest for supplemental recommendations."
preamble_estimated_tokens: 436
model_token_report: "https://studio.inttegro.com/machine/token-report.json"
preamble_questions: 5
preamble_source: "curated"
recommended_mcp_tools: ["create_order"]
estimated_tokens: 2283
token_estimate_method: "utf8_bytes_divided_by_4"
---

## Machine preamble

**Summary:** Authenticate server-side API calls with one opaque bearer key, diagnose failures without exposing it, and use the selected SDK only for its verified native API.

### Five questions

#### Q1. Where may the secret API key live?

Only in a trusted server-side secret store or runtime environment. If generated browser code, a mobile bundle, a URL, source control, logs, or model context would contain it, move the API call behind a server before proceeding.

#### Q2. What must each HTTP request send?

Use the Authorization header with the Bearer scheme and the complete opaque key. Do not parse the key or infer its environment from its characters; the selected SDK may handle the header when configured with the key.

#### Q3. How should a 401 be investigated?

Check the header shape, that the complete active secret reached the process, and that the process uses the intended environment. Never print or paste the secret while checking.

#### Q4. What if a key was exposed or a write outcome is uncertain?

Replace an exposed key through [API keys](https://studio.inttegro.com/machine/php/api/keys.md) and update the runtime secret. For a write whose first result is unknown, use [Idempotent requests](https://studio.inttegro.com/machine/php/api/idempotency.md) before retrying rather than inventing a new key or purchase.

#### Q5. How do wire and SDK response shapes differ?

The raw HTTP create-order response has an order envelope, while official SDKs return the order domain object directly. Follow the selected-language sample here, then [Orders](https://studio.inttegro.com/machine/php/api/orders.md) for the exact operation and native model; do not copy JSON property names as unverified SDK members.

## Document content

# Authentication

Inttegro authenticates API requests with an opaque bearer key. Keep the key in server-side secret storage and include it in the `Authorization` header for every request.

## Authenticate without moving the trust boundary

The key, 401, and exposure decisions are in the machine preamble above.

## Prerequisites

- An Inttegro application
- An API key generated from the dashboard
- A server-side runtime that can read secrets from its environment

## Send the bearer header

Set the header value to `Bearer ` followed by the complete opaque key:

```http
Authorization: Bearer <SECRET_KEY_TOKEN>
```

Do not parse the token, infer an environment from its characters, embed it in browser or mobile code, commit it to source control, or log it. A missing, malformed, or invalid credential returns `401 Unauthorized`.

## Make an authenticated request

This example creates a finalized order through the official SDKs. The raw HTTP response uses an `{ "order": { ... } }` envelope; the SDKs return the order domain object directly.

**Authenticated request — POST /orders/create**

```php
<?php

use Inttegro\Client;

$client = new Client($_ENV['INTTEGRO_API_KEY']);
$result = $client->orders->create([
  'request_meta' => [
    'idempotency_key' => 'auth-example-order-123',
  ],
  'finalize' => true,
  'customer_data' => [
    'name' => 'Akua Mensah',
    'email_address' => 'akua@example.com',
    'phone_number' => '+233544998605',
  ],
  'line_items' => [
    [
      'product' => [
        'name' => 'Premium Subscription',
        'price' => [
          'currency' => 'ghs',
          'value' => 5000,
        ],
        'quantity' => 1,
        'type' => \Inttegro\ProductType::Service,
      ],
      'type' => \Inttegro\LineItemType::Product,
    ],
  ],
]);
```

## Store credentials safely

Load the Inttegro key only in server-side code. Your process can still read
`INTTEGRO_API_KEY` from the environment at runtime; the important part is that
the value is injected from a protected secret system, not committed to source
control, copied into a public client bundle, or shared in plaintext.

```bash
INTTEGRO_API_KEY=<SECRET_KEY_TOKEN>
```

Choose the source of truth based on how your team ships software. If the key is
used by more than one service, deploy pipeline, or developer environment, keep
it in a dedicated secret store instead of maintaining separate `.env` files by
hand:

- [Doppler](https://docs.doppler.com/docs/secrets-setup-guide) or
  [Infisical](https://infisical.com/docs/documentation/platform/secrets-mgmt/overview)
  work well when you want one application-focused source of truth across local
  development, CI, and deployments.
- [1Password Environments](https://www.1password.dev/environments) is a good fit
  when developer credentials already live in 1Password and local commands should
  receive secrets without writing plaintext `.env` files.
- Use [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/create_secret.html),
  [Google Cloud Secret Manager](https://docs.cloud.google.com/secret-manager/docs/create-secret-quickstart),
  or
  [Azure Key Vault](https://learn.microsoft.com/en-us/azure/key-vault/secrets/quick-create-portal)
  when your application already runs in one of those clouds and can use its IAM
  or workload identity model.
- [HashiCorp Vault](https://developer.hashicorp.com/vault/tutorials/get-started)
  makes sense when your infrastructure team already operates Vault or needs
  centralized policy, dynamic credentials, and explicit lease management.

At the deployment boundary, prefer the secret feature provided by your host.
These platforms commonly expose the value to your application as an environment
variable, but store and protect it differently from ordinary configuration:

- On Railway, store `INTTEGRO_API_KEY` as a
  [sealed variable](https://docs.railway.com/variables#sealed-variables) so the
  value is available to builds and deployments but cannot be read back from the
  UI or API.
- On Vercel, use
  [sensitive environment variables](https://vercel.com/docs/environment-variables/sensitive-environment-variables)
  and scope them only to the environments that need to call Inttegro.
- On Netlify, mark the value as a secret with
  [Secrets Controller](https://docs.netlify.com/build/environment-variables/secrets-controller/).
- On Render, use
  [environment variables or secret files](https://render.com/docs/configure-environment-variables)
  and prefer secret files only when the runtime expects a credential on disk.
- On Fly.io, use
  [Fly secrets](https://fly.io/docs/apps/secrets/) instead of static values in
  `fly.toml`.
- On Cloudflare Workers, use
  [Worker secrets](https://developers.cloudflare.com/workers/configuration/secrets/)
  or
  [Cloudflare Secrets Store](https://developers.cloudflare.com/secrets-store/)
  for account-level reuse.
- In GitHub Actions, use
  [Actions secrets](https://docs.github.com/en/actions/how-tos/write-workflows/choose-what-workflows-do/use-secrets)
  instead of repository variables or workflow literals.

Use separate credentials for development, staging, and production, and restrict
access to the deployment identities that actually make Inttegro requests. Avoid
client-exposed prefixes such as `NEXT_PUBLIC_`, `VITE_`, or `EXPO_PUBLIC_`; an
Inttegro API key must only be loaded by server-side code. If a key may have been
disclosed, generate a replacement, deploy it, verify requests with the new
credential, and retire the old key.

## Handle authentication failures

A `401 Unauthorized` response means Inttegro could not authenticate the request. Verify that the header uses the exact `Bearer <token>` format, the complete token was loaded, and the credential is still active. Do not print the key while diagnosing the failure.

Authentication proves which application made the request. It does not by itself prove a customer's identity or authorize a payment; keep those decisions in the corresponding checkout or verification flow.

## Related resources

- [API keys](https://studio.inttegro.com/machine/php/api/keys.md#generate-a-key) - Generate and protect an opaque credential
- [Create an order](https://studio.inttegro.com/machine/php/api/orders.md#create-an-order) - Complete order contract
- [Quickstart](https://studio.inttegro.com/machine/php/quickstart.md#create-a-finalized-order) - Create an order and open hosted checkout
- [Verify users with OTP](https://studio.inttegro.com/machine/php/guides/verify-with-otp.md#verify-the-submitted-token) - Customer verification boundary
