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.
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:
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
- cURL
- TypeScript
- Go
- Python
- PHP
- Ruby
- Java
- C#
response=$(curl https://api.inttegro.com/orders/create \
-H "Authorization: Bearer $INTTEGRO_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: auth-example-order-123" \
-d '{
"finalize": true,
"customer_data": {
"name": "Akua Mensah",
"email_address": "[email protected]",
"phone_number": "+233544998605"
},
"line_items": [{
"product": {
"name": "Premium Subscription",
"price": { "currency": "ghs", "value": 5000 },
"quantity": 1,
"type": "service"
},
"type": "product"
}]
}')
invoice_url=$(jq -er '.order.invoice.format.web.url' <<< "$response")
import * as Inttegro from '@inttegro/inttegro-sdk'
const inttegro = new Inttegro.InttegroClient({
apiKey: process.env.INTTEGRO_API_KEY!,
})
const result = await inttegro.orders.create({
requestMeta: {
idempotencyKey: "auth-example-order-123",
},
finalize: true,
customerData: {
name: "Akua Mensah",
phoneNumber: "+233544998605",
},
lineItems: [
{
product: {
name: "Premium Subscription",
price: {
currency: "ghs",
value: 5000,
},
quantity: 1,
type: Inttegro.ProductTypes.Service,
},
type: Inttegro.LineItemTypes.Product,
},
],
})
package main
import (
"context"
"log"
"os"
inttegro "github.com/zebodotdev/inttegro-sdk-go/v4"
"github.com/zebodotdev/inttegro-sdk-go/v4/money"
)
func main() {
ctx := context.Background()
client := inttegro.NewClient(os.Getenv("INTTEGRO_API_KEY"))
params := inttegro.OrderCreateParams{
RequestMeta: &inttegro.RequestMeta{
IdempotencyKey: "auth-example-order-123",
},
Finalize: inttegro.Bool(true),
CustomerData: &inttegro.CustomerData{
Name: "Akua Mensah",
PhoneNumber: "+233544998605",
},
LineItems: []inttegro.OrderLineItemParams{
{
Product: &inttegro.ProductLineItemParams{
Name: "Premium Subscription",
Price: inttegro.PriceParams{
AmountParams: money.AmountParams{
Currency: money.GHS,
Value: 5000,
},
},
Quantity: 1,
Type: inttegro.ProductTypeService,
},
Type: inttegro.LineItemTypeProduct,
},
},
}
result, err := client.Orders.Create(ctx, params)
if err != nil {
log.Fatal(err)
}
_ = result
}
import os
import inttegro
client = inttegro.InttegroClient(api_key=os.environ["INTTEGRO_API_KEY"])
result = client.orders.create(inttegro.orders.CreateRequest(
request_meta=inttegro.orders.RequestMeta(
idempotency_key="auth-example-order-123",
),
finalize=True,
customer_data=inttegro.orders.Customer(
name="Akua Mensah",
phone_number="+233544998605",
),
line_items=[
inttegro.orders.ProductLineItem(
product=inttegro.orders.Product(
name="Premium Subscription",
price=inttegro.orders.PriceParams(
currency=inttegro.Currency.GHS,
value=5000,
),
quantity=1,
type=inttegro.ProductType.SERVICE,
),
type=inttegro.LineItemType.PRODUCT,
),
],
))
<?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',
'phone_number' => '+233544998605',
],
'line_items' => [
[
'product' => [
'name' => 'Premium Subscription',
'price' => [
'currency' => 'ghs',
'value' => 5000,
],
'quantity' => 1,
'type' => \Inttegro\ProductType::Service,
],
'type' => \Inttegro\LineItemType::Product,
],
],
]);
require "inttegro"
client = Inttegro::Client.new(api_key: ENV.fetch("INTTEGRO_API_KEY"))
result = client.orders.create(
request_meta: {
idempotency_key: "auth-example-order-123",
},
finalize: true,
customer_data: {
name: "Akua Mensah",
phone_number: "+233544998605",
},
line_items: [
{
product: {
name: "Premium Subscription",
price: {
currency: "ghs",
value: 5000,
},
quantity: 1,
type: Inttegro::ProductType::SERVICE,
},
type: Inttegro::LineItemType::PRODUCT,
},
]
)
import com.inttegro.Client;
import com.inttegro.orders.OrderCreateParams;
import com.inttegro.RequestMeta;
import com.inttegro.customers.CustomerData;
import com.inttegro.orders.OrderLineItemParams;
import com.inttegro.orders.ProductLineItemParams;
import com.inttegro.prices.PriceParams;
import com.inttegro.money.Currency;
import com.inttegro.products.ProductType;
public class Example {
public static void main(String[] args) throws Exception {
var client = new Client(System.getenv("INTTEGRO_API_KEY"));
var params = OrderCreateParams.builder()
.requestMeta(RequestMeta.builder()
.idempotencyKey("auth-example-order-123")
.build())
.finalizeOrder(true)
.customerData(CustomerData.builder()
.name("Akua Mensah")
.phoneNumber("+233544998605")
.build())
.lineItem(OrderLineItemParams.product(ProductLineItemParams.builder()
.name("Premium Subscription")
.price(PriceParams.of(Currency.GHS, 5000))
.quantity(1L)
.type(ProductType.SERVICE)
.build()))
.build();
var result = client.orders().create(params);
}
}
using Inttegro;
using var inttegro = new InttegroClient(
Environment.GetEnvironmentVariable("INTTEGRO_API_KEY")!
);
var result = await inttegro.Orders.CreateAsync(new {
request_meta = new {
idempotency_key = "auth-example-order-123",
},
finalize = true,
customer_data = new {
name = "Akua Mensah",
phone_number = "+233544998605",
},
line_items = new[] {
new {
product = new {
name = "Premium Subscription",
price = new {
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.
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 or Infisical work well when you want one application-focused source of truth across local development, CI, and deployments.
- 1Password Environments is a good fit
when developer credentials already live in 1Password and local commands should
receive secrets without writing plaintext
.envfiles. - Use AWS Secrets Manager, Google Cloud Secret Manager, or Azure Key Vault when your application already runs in one of those clouds and can use its IAM or workload identity model.
- HashiCorp Vault 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_KEYas a sealed variable 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 and scope them only to the environments that need to call Inttegro.
- On Netlify, mark the value as a secret with Secrets Controller.
- On Render, use environment variables or secret files and prefer secret files only when the runtime expects a credential on disk.
- On Fly.io, use
Fly secrets instead of static values in
fly.toml. - On Cloudflare Workers, use Worker secrets or Cloudflare Secrets Store for account-level reuse.
- In GitHub Actions, use Actions 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 - Generate and protect an opaque credential
- Create an order - Complete order contract
- Quickstart - Create an order and open hosted checkout
- Verify users with OTP - Customer verification boundary