Skip to content

Authentication

The Owem Pay external API uses a three-layer security model: API Key + Secret, per-request HMAC-SHA512 signature, and mandatory IP whitelist.

Layer Overview

HTTP Request
  |
  +- 1. IP Whitelist --- Unauthorized IP? -> 403 Forbidden
  |
  +- 2. API Key + Secret --- Invalid credentials? -> 401 Unauthorized
  |
  +- 3. HMAC-SHA512 --- Invalid signature? -> 401 Unauthorized
       |
       +- Request accepted -> Business logic

Layer 1 -- API Key + Secret

All requests must include the Authorization header:

Authorization: ApiKey {client_id}:{client_secret}
ComponentDescriptionPrefix
client_idPublic API Key identifiercli_
client_secretSecret key (we only store the hash)sk_

The secret is never stored in plain text. When a request arrives, the submitted secret is compared against the stored hash. If it does not match, the request is rejected before reaching business logic.

Alternative format -- Basic Auth with base64:

Authorization: Basic {base64(client_id:client_secret)}

Layer 2 -- HMAC-SHA512

Transactional requests (POST, PUT, PATCH) require an HMAC-SHA512 signature of the body in the hmac header. Validation uses constant-time comparison to prevent timing attacks.

See HMAC-SHA512 for implementation examples in 6 languages.

Layer 3 -- IP Whitelist

Every API Key must have at least one IP in the whitelist. Requests from unauthorized IPs are rejected with 403 Forbidden, even with valid credentials. Configure the whitelist in the Merchant Portal when creating or editing the API Key.

Supports individual IPs and CIDR notation (e.g., 172.20.16.0/20).

Required Headers

HeaderValueRequired
AuthorizationApiKey {client_id}:{client_secret}Yes -- all requests
Content-Typeapplication/jsonYes -- requests with body
hmacHMAC-SHA512 signature in hexadecimalYes -- POST/PUT/PATCH only
Idempotency-KeyUnique key for deduplication (max 256 chars)Optional -- POST only

Complete Example

bash
CLIENT_ID="cli_a1b2c3d4e5f6"
CLIENT_SECRET="sk_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef01"

# Balance query (GET -- no HMAC)
curl -X GET https://api.owem.com.br/api/external/balance \
  -H "Authorization: ApiKey $CLIENT_ID:$CLIENT_SECRET"

# PIX Cash-Out (POST -- with HMAC + Idempotency-Key)
BODY='{"amount":3000,"pix_key":"12345678901","pix_key_type":"cpf","description":"Pagamento"}'
HMAC=$(echo -n "$BODY" | openssl dgst -sha512 -hmac "$CLIENT_SECRET" | awk '{print $2}')

curl -X POST https://api.owem.com.br/api/external/pix/cash-out \
  -H "Authorization: ApiKey $CLIENT_ID:$CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -H "hmac: $HMAC" \
  -H "Idempotency-Key: cashout-order-9876" \
  -d "$BODY"

Additional Protections

ProtectionDescription
Rate Limiting60,000 req/min per IP (authenticated). 5 req/min (unauthenticated)
Cloud Armor (WAF)Web application firewall protecting the cluster
HTTPS + TLS 1.2+Mandatory encryption on all connections
HSTSBrowsers forced to use HTTPS

Why HMAC-SHA512 and not mTLS?

mTLS (mutual TLS) authenticates the connection, not the content. If the connection is authenticated, all requests pass through without individual validation.

HMAC validates each request separately. Even within a valid connection, any change to the payload causes the request to be rejected.

AspectmTLSHMAC-SHA512
ValidatesTLS channelRequest payload
ManagementX.509 certificates (issuance, rotation, revocation, CRL/OCSP)Generate pair, update, invalidate
Operational riskExpired certificates -- frequent cause of incidentsKey is a simple string
Content integrityNoYes

TLS already ensures transport encryption. HMAC adds payload integrity and authenticity -- something that mTLS alone does not cover.

Error Responses

401 -- Missing Credentials

json
{
  "error": {
    "status": 401,
    "message": "Missing API key credentials. Use Authorization: ApiKey <client_id>:<client_secret>"
  }
}

403 -- Unauthorized IP

json
{
  "error": {
    "status": 403,
    "message": "Request IP not in API key whitelist"
  }
}

429 -- Rate Limit Exceeded

json
{
  "error": {
    "status": 429,
    "message": "Too Many Requests"
  }
}

Security

  • Never expose the client_secret in frontend code or public repositories
  • Use environment variables on your server
  • The API Key is permanent -- it does not expire, but can be revoked in the Merchant Portal
  • Configure allowed IPs in the whitelist

Owem Pay Instituição de Pagamento — ISPB 37839059