PHPackages                             pumasoft/puma-api - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. pumasoft/puma-api

ActiveLibrary[API Development](/categories/api)

pumasoft/puma-api
=================

Pumasoft API certificate issuer engine

v1.4.9(4y ago)026proprietaryPHP

Since Sep 25Pushed 4mo ago1 watchersCompare

[ Source](https://github.com/Volted/PumaApi)[ Packagist](https://packagist.org/packages/pumasoft/puma-api)[ RSS](/packages/pumasoft-puma-api/feed)WikiDiscussions master Synced today

READMEChangelog (10)DependenciesVersions (16)Used By (0)

PumaAPI
=======

[](#pumaapi)

[![Version](https://camo.githubusercontent.com/34e695c6016bc2a934a96bed696e29b2f2ab562a7134d65a55d00653cd506bea/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f76657273696f6e2d312e302e302d626c75652e737667)](https://camo.githubusercontent.com/34e695c6016bc2a934a96bed696e29b2f2ab562a7134d65a55d00653cd506bea/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f76657273696f6e2d312e302e302d626c75652e737667)[![PHP](https://camo.githubusercontent.com/26bf6e41ce21eb39db7d8ace00cc112ed5be5e9d8fbd657254521fcea77983b9/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e322b2d707572706c652e737667)](https://camo.githubusercontent.com/26bf6e41ce21eb39db7d8ace00cc112ed5be5e9d8fbd657254521fcea77983b9/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e322b2d707572706c652e737667)[![License](https://camo.githubusercontent.com/ff80df3d4da70a17ecce6d38ebd697ca802f6c4e81ad00445f6d6dd612b3b14f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d6d69742e737667)](https://camo.githubusercontent.com/ff80df3d4da70a17ecce6d38ebd697ca802f6c4e81ad00445f6d6dd612b3b14f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d6d69742e737667)

API Gateway for Puma Services
-----------------------------

[](#api-gateway-for-puma-services)

**PumaAPI** is a lightweight micro API module designed to parse, validate, and authenticate REST requests based on a simple, file-driven contract architecture. It leverages JWT (JSON Web Token) authentication and provides a clean, declarative way to define your API endpoints through JSON contract files.

---

Table of Contents
-----------------

[](#table-of-contents)

- [Features](#features)
- [Requirements](#requirements)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Architecture Overview](#architecture-overview)
- [Manifest Structure](#manifest-structure)
    - [Directory Layout](#directory-layout)
    - [Contract File Format](#contract-file-format)
- [Validation Rules](#validation-rules)
- [JWT Authentication](#jwt-authentication)
- [Service Configuration](#service-configuration)
- [Making Outbound API Calls](#making-outbound-api-calls)
- [Certificate Object](#certificate-object)
- [Error Handling](#error-handling)
- [Global Configuration Flags](#global-configuration-flags)
- [Complete Usage Example](#complete-usage-example)
- [Security Considerations](#security-considerations)
- [API Reference](#api-reference)

---

Features
--------

[](#features)

- 📁 **File-Based Contract System** - Define API contracts using simple JSON files organized by HTTP method
- 🔐 **JWT Authentication** - Built-in JWT parsing, validation, and signature verification
- ✅ **Request Validation** - Automatic validation of headers, body, and JWT payloads against contracts
- 🧹 **Request Sanitization** - Returns only contracted fields, preventing data leakage
- 📤 **Outbound API Caller** - Built-in HTTP client for making authenticated requests to other services
- 🎯 **RESTful Design** - Supports GET, POST, PUT, and DELETE methods
- ⚡ **Lightweight** - Minimal dependencies (only `ext-json` and `ext-curl`)
- 🛡️ **Secure by Default** - Production-ready security with optional development flags

---

Requirements
------------

[](#requirements)

- PHP 5.6 or higher
- `ext-json` extension
- `ext-curl` extension
- Apache with mod\_rewrite (recommended)

---

Installation
------------

[](#installation)

```
composer require pumasoft/puma-api
```

### Manual Installation

[](#manual-installation)

1. Clone or download the repository
2. Include the autoloader or manually require the necessary files

```
require_once 'path/to/PumaAPI/Controller/API.php';
```

---

Quick Start
-----------

[](#quick-start)

```
$cert = $Puma->getCertificate(); // Access validated request data
$method = $cert->getRequestedMethod(); // e.g., 'get'
$controller = $cert->getRequestedRoot(); // e.g., 'auth'
$resource = $cert->getRequestedResource(); // e.g., 'bearing_username'
$body = $cert->getRequestBody(); // Validated request body
$jwtPayload = $cert->getRequestedJWTPayload(); // JWT claims
```

---

Architecture Overview
---------------------

[](#architecture-overview)

PumaAPI follows a contract-first approach where API behavior is defined through JSON manifest files:

```
┌─────────────────────────────────────────────────────────────────┐
│ Incoming Request                                                │
└─────────────────────────────────────────────────────────────────┘
                   │
                   ▼
┌─────────────────────────────────────────────────────────────────┐
│ API Controller                                                  │
│ ┌──────────────┐ ┌──────────────┐ ┌────────────────────────┐     │
│ │Parse Request │→│Load Contract │→│ Validate & Authenticate│     │
│ └──────────────┘ └──────────────┘ └────────────────────────┘     │
└─────────────────────────────────────────────────────────────────┘
                   │
                   ▼
┌─────────────────────────────────────────────────────────────────┐
│ Certificate Object                                              │
│ (Sanitized request data + Response contract)                    │
└─────────────────────────────────────────────────────────────────┘

```

### Core Components

[](#core-components)

ComponentDescription`API`Main controller that orchestrates the request lifecycle`Request`Parses and structures incoming HTTP requests`Contract`Loads and validates requests against JSON contracts`Validator`Performs field-level validation based on rules`Tokenizer`Handles JWT generation, parsing, and verification`Certificate`Contains validated request data for controller use`Caller`Makes outbound HTTP requests to other services`Rawr`Custom exception handler with HTTP response support---

Manifest Structure
------------------

[](#manifest-structure)

### Directory Layout

[](#directory-layout)

The manifest directory follows a RESTful hierarchy:

```
__manifest/
├── service.ini # Service configuration & JWT secrets
├── get/
│   ├── auth/
│   │   ├── login.json
│   │   └── refresh.json
│   └── users/
│       ├── profile.json
│       └── list.json
├── post/
│   ├── auth/
│   │   └── register.json
│   └── users/
│       └── create.json
├── put/
│   └── users/
│       └── update.json
└── delete/
    └── users/
        └── remove.json

```

**URL Mapping:**

HTTP RequestContract File`GET /auth/login``__manifest/get/auth/login.json``POST /users/create``__manifest/post/users/create.json``PUT /users/update``__manifest/put/users/update.json``DELETE /users/remove``__manifest/delete/users/remove.json`### Contract File Format

[](#contract-file-format)

Each JSON contract defines the expected request format and response structure:

```
{
  "Request": {
    "Headers": {
      "Content-Type": "application/json",
      "Authorization": {
        "Header": {
          "alg": "",
          "typ": ""
        },
        "Payload": {
          "iss": "",
          "exp": ""
        },
        "Signature": ""
      }
    },
    "Body": {
      "username": "",
      "password": ""
    }
  },
  "Response": {
    "Controller": "Auth",
    "Headers": {
      "Content-Type": "application/json"
    },
    "Body": {
      "result": ""
    }
  }
}
```

---

Validation Rules
----------------

[](#validation-rules)

Validation rules are specified using the `` syntax. Available built-in rules:

RuleDescriptionExample``Non-empty string value`"username": ""```Integer value`"age": ""```JWT algorithm matching service.ini`"alg": ""```JWT type matching service.ini`"typ": ""```Issuer registered in service.ini`"iss": ""```Valid Unix timestamp`"exp": ""`### Exact Value Matching

[](#exact-value-matching)

If no rule syntax is used, the validator expects an exact match:

```
{
  "Content-Type": "application/json"
}
```

This requires the `Content-Type` header to be exactly `application/json`.

---

JWT Authentication
------------------

[](#jwt-authentication)

PumaAPI uses JWT Bearer tokens for authentication. Tokens must be sent in the `Authorization` header:

```
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

```

### Token Structure

[](#token-structure)

```
┌─────────────────────────────────────────────────────────────┐
│ Header.Payload.Signature                                    │
│ ───────┬───────────────┬──────────────                     │
│        │               │                                      │
│ ┌────┴────┐ ┌─────┴─────┐ ┌────────────────┐                │
│ │ {"alg": │ │ {"iss":   │ │ HMACSHA256(  │                │
│ │ "HS256",│ │ "app",    │ │ header+"."+  │                │
│ │ "typ":  │ │ "exp":    │ │ payload,     │                │
│ │ "JWT"}  │ │ 1234567}  │ │ secret)      │                │
│ └─────────┘ └───────────┘ └────────────────┘                │
└─────────────────────────────────────────────────────────────┘

```

### Generating Tokens

[](#generating-tokens)

Use the `Tokenizer` class to generate new tokens:

```
use PumaAPI\Model\Tokenizer;

$tokenizer = new Tokenizer('/path/to/__manifest');
$token = $tokenizer->generateNewToken(
    $tokenizer->getCurrentIssuer(),
    [
        'alg' => $tokenizer->getCurrentAlgorithm(),
        'typ' => $tokenizer->getCurrentTokenType()
    ],
    [
        'iss' => $tokenizer->getCurrentIssuer(),
        'exp' => time() + 3600
    ]
);
```

---

Service Configuration
---------------------

[](#service-configuration)

Create a `service.ini` file in your manifest directory:

```
[ident]
iss = my-service-name

[token]
head[alg] = HS256
head[typ] = JWT

[auth]
my-app = your-secret-key-here
partner-service = another-secret-key
trusted-client = client-specific-secret
```

### Configuration Sections

[](#configuration-sections)

SectionPurpose`[ident]`Service identity (issuer name)`[token]`Default JWT header configuration`[auth]`Registered issuers and their secret keys---

Making Outbound API Calls
-------------------------

[](#making-outbound-api-calls)

Use the `Caller` class to make authenticated requests to other services:

```
use PumaAPI\Model\Caller;
use PumaAPI\Model\Tokenizer;

// Generate a token for the target service
$tokenizer = new Tokenizer();
$jwt = $tokenizer->generateNewToken(
    $tokenizer->getCurrentIssuer(),
    [
        'alg' => $tokenizer->getCurrentAlgorithm(),
        'typ' => $tokenizer->getCurrentTokenType()
    ],
    [
        'iss' => $tokenizer->getCurrentIssuer(),
        'exp' => time() + 3600
    ]
);

// Create the caller
$caller = new Caller(
    Caller::POST,
    'https://api.partner.com/users/create',
    ['Content-Type' => 'application/json'],
    $jwt,
    ['name' => 'John Doe', 'email' => 'john@example.com']
);

// Execute the request
$caller->initRequest();

// Get the response
$response = $caller->getResponse(); // Returns: ['Code' => 200, 'Headers' => [...], 'Body' => '...']

// Parse JWT from response headers
$responseJWT = $caller->getJWTResponse(); // Returns: ['Head' => [...], 'Payload' => [...], 'Signature' => '...']
```

---

Certificate Object
------------------

[](#certificate-object)

After successful validation, the `Certificate` object provides access to sanitized request data:

```
$cert = $Puma->getCertificate();

// Request routing
$cert->getRequestedMethod(); // HTTP method (lowercase)
$cert->getRequestedRoot(); // Controller/root path
$cert->getRequestedResource(); // Resource identifier

// Request data (only contracted fields)
$cert->getRequestHeaders(); // Validated headers
$cert->getRequestBody(); // Validated body

// JWT data
$cert->getRequestedJWTHead(); // JWT header claims
$cert->getRequestedJWTPayload(); // JWT payload claims

// Response contract
$cert->getResponseContract(); // Expected response structure
```

---

Error Handling
--------------

[](#error-handling)

PumaAPI uses the `Rawr` exception class for structured error handling:

### HTTP Status Codes

[](#http-status-codes)

CodeConstantDescription400`Rawr::BAD_REQUEST`Invalid request format or missing fields401`Rawr::UNAUTHORIZED`Invalid or missing authentication403`Rawr::FORBIDDEN`Access denied404`Rawr::NOT_FOUND`Resource or endpoint not found405`Rawr::METHOD_NOT_ALLOWED`HTTP method not supported500`Rawr::INTERNAL_ERROR`Server-side error### Error Response Format

[](#error-response-format)

**Production (default):**

```
{
  "error": "bad request"
}
```

**Development (with `PUMA_API_SEND_EXCEPTIONS_IN_RESPONSE`):**

```
{
  "client": {"error": "bad request"},
  "server": "body variable 'username' is missing"
}
```

---

Global Configuration Flags
--------------------------

[](#global-configuration-flags)

> ⚠️ **Warning:** These flags are intended for development only. Never enable them in production!

```
// Log exceptions to PHP error log
define('PUMA_API_LOG_EXCEPTIONS', true);

// Include detailed error messages in JSON response
define('PUMA_API_SEND_EXCEPTIONS_IN_RESPONSE', true);

// Disable SSL certificate verification for cURL requests
define('PUMA_API_DO_NOT_VALIDATE_SSL', true);
```

Define these constants in your bootstrap file **before** instantiating the API class. The presence of the constant enables the feature (the value is ignored).

---

Complete Usage Example
----------------------

[](#complete-usage-example)

### 1. Project Structure

[](#1-project-structure)

```
project/
├── __manifest/
│   ├── service.ini
│   └── post/
│       └── auth/
│           └── login.json
├── controllers/
│   └── AuthController.php
├── index.php
└── .htaccess

```

### 2. Apache Rewrite Rules (.htaccess)

[](#2-apache-rewrite-rules-htaccess)

```
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]

```

### 3. Contract File (\_\_manifest/post/auth/login.json)

[](#3-contract-file-__manifestpostauthloginjson)

```
{
  "Request": {
    "Headers": {
      "Content-Type": "application/json",
      "Authorization": {
        "Header": {
          "alg": "",
          "typ": ""
        },
        "Payload": {
          "iss": "",
          "exp": ""
        }
      }
    },
    "Body": {
      "username": "",
      "password": ""
    }
  },
  "Response": {
    "Controller": "Auth",
    "Action": "login"
  }
}
```

### 4. Service Configuration (\_\_manifest/service.ini)

[](#4-service-configuration-__manifestserviceini)

```
[ident]
iss = my-api

[token]
head[alg] = HS256
head[typ] = JWT

[auth]
my-api = your-super-secret-key-here
mobile-app = mobile-app-secret-key
```

### 5. Entry Point (index.php)

[](#5-entry-point-indexphp)

```
$cert = $Puma->getCertificate();

// Route to appropriate controller
$controllerName = $cert->getResponseContract()['Controller'] ?? 'Default';
$controllerClass = "Controllers\\{$controllerName}Controller";

if (class_exists($controllerClass)) {
    $controller = new $controllerClass($cert);
    $controller->handle();
} else {
    http_response_code(500);
    echo json_encode(['error' => 'Controller not found']);
}
```

### 6. Controller (controllers/AuthController.php)

[](#6-controller-controllersauthcontrollerphp)

```
namespace Controllers;

use PumaAPI\Model\Tokenizer;

class AuthController {
    private $cert;

    public function __construct($cert) {
        $this->cert = $cert;
    }

    public function handle() {
        $body = $this->cert->getRequestBody();
        $username = $body['username'];
        $password = $body['password'];

        // Validate credentials (implement your logic)
        if ($this->validateCredentials($username, $password)) {
            $tokenizer = new Tokenizer();
            $token = $tokenizer->generateNewToken(
                $tokenizer->getCurrentIssuer(),
                [
                    'alg' => $tokenizer->getCurrentAlgorithm(),
                    'typ' => $tokenizer->getCurrentTokenType()
                ],
                [
                    'iss' => $tokenizer->getCurrentIssuer(),
                    'exp' => time() + 3600,
                    'sub' => $username
                ]
            );

            header('Content-Type: application/json');
            header('Authorization: Bearer ' . $token);
            echo json_encode(['result' => 'success', 'message' => 'Login successful']);
        } else {
            http_response_code(401);
            echo json_encode(['error' => 'Invalid credentials']);
        }
    }

    private function validateCredentials($username, $password) {
        // Implement your authentication logic
        return true;
    }
}
```

---

Security Considerations
-----------------------

[](#security-considerations)

1. **Keep service.ini secure** - This file contains secret keys; ensure it's not web-accessible
2. **Use HTTPS** - Always use SSL/TLS in production
3. **Rotate secrets regularly** - Update JWT signing keys periodically
4. **Set short expiration times** - Use reasonable `exp` values for tokens
5. **Disable development flags** - Never use `PUMA_API_*` constants in production
6. **Validate all input** - Define comprehensive contracts for all endpoints

---

API Reference
-------------

[](#api-reference)

### PumaAPI\\Controller\\API

[](#pumaapicontrollerapi)

MethodReturnsDescription`__construct($manifestPath = false)``API`Initialize with optional manifest path`getCertificate()``Certificate`Get validated request certificate### PumaAPI\\Model\\Certificate

[](#pumaapimodelcertificate)

MethodReturnsDescription`getRequestedMethod()``string`HTTP method (lowercase)`getRequestedRoot()``string`Controller/root segment`getRequestedResource()``string`Resource path`getRequestHeaders()``array`Validated request headers`getRequestBody()``array`Validated request body`getRequestedJWTHead()``array`JWT header claims`getRequestedJWTPayload()``array`JWT payload claims`getResponseContract()``array`Response contract definition### PumaAPI\\Model\\Tokenizer

[](#pumaapimodeltokenizer)

MethodReturnsDescription`__construct($configPath = false)``Tokenizer`Initialize with config path`generateNewToken($issuer, $head, $body)``string`Generate complete JWT`generateSignatureFor($issuer, $head, $body)``string`Generate signature only`getCurrentIssuer()``string`Get configured issuer`getCurrentAlgorithm()``string`Get configured algorithm`getCurrentTokenType()``string`Get configured token type`isAuthentic($tokenContent, $issuer)``bool`Verify token signature`validExpiryDate($tokenHead)``bool`Check if token is expired`extractJWT($headers)``array`Parse JWT from headers (static)### PumaAPI\\Model\\Caller

[](#pumaapimodelcaller)

MethodReturnsDescription`__construct($method, $url, $headers, $jwt, $body)``Caller`Initialize request`initRequest()``void`Execute the HTTP request`getResponse()``array`Get response (code, headers, body)`getJWTResponse()``array`Parse JWT from response---

Important
---------

[](#important)

This is a personal side project developed independently in my own time, using my own equipment and resources. It has no connection to any employer, client, or commercial work.

###  Health Score

33

—

LowBetter than 75% of packages

Maintenance52

Moderate activity, may be stable

Popularity6

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity58

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~1 days

Total

15

Last Release

1666d ago

Major Versions

v0.1 → v1.3.02021-09-27

### Community

Maintainers

![](https://www.gravatar.com/avatar/167e8c10a9a4167c1d15e18a501050ad32690d4e7c7b861cbd8bba4988959200?d=identicon)[PumaSoft](/maintainers/PumaSoft)

---

Top Contributors

[![Volted](https://avatars.githubusercontent.com/u/13600910?v=4)](https://github.com/Volted "Volted (55 commits)")

### Embed Badge

![Health badge](/badges/pumasoft-puma-api/health.svg)

```
[![Health](https://phpackages.com/badges/pumasoft-puma-api/health.svg)](https://phpackages.com/packages/pumasoft-puma-api)
```

###  Alternatives

[stripe/stripe-php

Stripe PHP Library

4.0k143.3M475](/packages/stripe-stripe-php)[twilio/sdk

A PHP wrapper for Twilio's API

1.6k92.9M270](/packages/twilio-sdk)[knplabs/github-api

GitHub API v3 client

2.2k15.8M187](/packages/knplabs-github-api)[facebook/php-business-sdk

PHP SDK for Facebook Business

90121.9M34](/packages/facebook-php-business-sdk)[meilisearch/meilisearch-php

PHP wrapper for the Meilisearch API

73813.7M114](/packages/meilisearch-meilisearch-php)[google/gax

Google API Core for PHP

263103.1M452](/packages/google-gax)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
