A self-hosted Outbound API Gateway. Register any third-party API once, call it from a single endpoint. OAuth 2.0, quota management, rate limiting & response formatting. Built with Django + DRF.
See the codeA self-hosted Django platform to manage, proxy, and rate-limit calls to third-party APIs — with OAuth 2.0 support, per-user quota, and a unified REST interface.
Don't want to deploy and maintain the infrastructure yourself? A fully managed SaaS version of Asstgr is available at:
👉 https://www.asstgr.com/home/
It offers a complete management interface:
No need to install PostgreSQL, run Django migrations, or configure a .env file — just create an account and start registering your APIs.
The self-hosted version (this repository) remains available for users who want full control over their infrastructure and data.
Built with Django + DRF. Contributions welcome.
If Asstgr saved you time or gave you ideas, a GitHub star goes a long way — it helps other developers discover the project and keeps me motivated to build more.
⭐ Star it on GitHub — it takes 2 seconds and means a lot. Thank you!
Asstgr is an API Abstraction Layer: instead of integrating third-party APIs directly into your apps, you register them once in Asstgr, describe their endpoints and parameters, and call them through a single, secured interface.
Think of it as your own private RapidAPI — self-hosted, fully programmable via REST, with fine-grained quota control.
Your app ──► Asstgr (/api/v1/...execute/) ──► Stripe / OpenWeatherMap / GitHub / any API
│
├─ Auth (API Key or OAuth2)
├─ Quota enforcement
├─ Request logging
└─ Response formatting
/api/v1/.../execute/ with parametersclient_credentials, authorization_code, and password flows, with automatic token refreshsk-...) to authenticate against Asstgrquota_cost| Layer | Technology |
|---|---|
| Backend | Django 5.x + Django REST Framework |
| Auth | Custom API Key + SimpleJWT + OAuth 2.0 |
| Database | PostgreSQL |
| Async | Daphne / Django Channels (ASGI) |
| Throttling | DRF SimpleRateThrottle |
asstgrv7/
├── asstgrv7/ # Django project (settings, urls, asgi)
│ ├── settings/
│ │ └── dev.py
│ └── urls.py
│
├── api_management/ # Core: API registry, models, OAuth service
│ ├── models.py # API, Endpoint, Parameter, Header, Method, APILog, APICallQuota
│ ├── utils.py # Request building, response formatting (JSONCleaner)
│ ├── oauth_service.py # OAuthService: fetch, refresh, save tokens
│ ├── views_oauth.py # OAuth authorize / callback views
│ └── admin.py
│
├── api_public/ # Public REST API (v1)
│ ├── views.py # All API views (CRUD + Execute + OAuth)
│ ├── models.py # PublicAPIKey
│ ├── serializers.py
│ ├── authentication.py # APIKeyAuthentication
│ ├── permissions.py # IsAPIKeyAuthenticated, HasSufficientQuota
│ ├── throttling.py # Burst + Sustained throttles
│ ├── limits.py # LIMITS constants
│ └── urls.py
│
└── users/ # Custom user model (AbstractUser)
├── models.py
└── admin.py
Asstgr's database is organized around a hierarchy of objects. Here's a quick overview of the core models and their key fields:
APIThe top-level object representing a third-party API.
| Field | Type | Description |
|---|---|---|
name | string | Display name |
url | URL | Base URL of the third-party API |
auth_required | bool | Whether authentication is needed |
quota_cost | int | Credits consumed per call (default: 1) |
is_active / is_blocked | bool | Availability flags |
EndpointA path under an API (e.g. /weather).
| Field | Type | Description |
|---|---|---|
path | string | Path appended to the API base URL |
description | string | What the endpoint does |
example_request / example_response | text | Optional documentation |
ParameterA parameter attached to an endpoint.
| Field | Type | Description |
|---|---|---|
name | string | Parameter name |
param_type | enum | query, path, or body |
data_type | enum | STRING, INTEGER, BOOLEAN, DATE, JSON |
required | bool | Whether the parameter is mandatory |
default_value | string | Optional fallback value |
stored_value | string | Pre-filled value (for non-editable params) |
editable | bool | Whether the caller can override the value |
HeaderA fixed HTTP header sent with every call to an endpoint (e.g. Content-Type, X-Api-Version).
MethodThe HTTP method(s) allowed on an endpoint (GET, POST, PUT, DELETE).
OAuthConfigOAuth 2.0 configuration attached to an API (one per API).
| Field | Description |
|---|---|
grant_type | client_credentials, authorization_code, or password |
token_url | Token endpoint URL |
client_id / client_secret_encrypted | OAuth credentials |
scope | Space-separated scopes |
access_token / refresh_token | Cached token values |
token_expires_at | Expiry datetime (null = permanent token) |
APICallQuotaPer-user monthly credit tracking.
| Field | Description |
|---|---|
monthly_limit | Credit budget (null = unlimited) |
call_count | Credits consumed so far this month |
month / year | Billing period |
APILogAudit record created after every executed call — stores the user, endpoint, HTTP method, request/response data, status code, and response size.
git clone https://github.com/asstgr/asstgropensource.git
cd asstgropensource
python -m venv venv && source venv/bin/activate
pip install -r requirements.txt
Create a .env file at the project root:
DJANGO_SECRET_KEY=your-secret-key
DB_NAME_local=asstgr_db
DB_USER_local=postgres
DB_PASSWORD_local=your-password
DB_HOST_local=localhost
DB_PORT_local=5432
python manage.py migrate --settings=asstgrv7.settings.dev
python manage.py createsuperuser --settings=asstgrv7.settings.dev
python manage.py runserver --settings=asstgrv7.settings.dev
The API is available at http://localhost:8000/api/v1/.
All requests to /api/v1/ must include your API key:
Authorization: Api-Key sk-xxxxxxxxxxxxxxxxxxxxxxxx
Generate a key from the admin panel or via:
POST /api/v1/keys/
Content-Type: application/json
{ "name": "My production key" }
POST /api/v1/apis/
{
"name": "OpenWeatherMap",
"url": "https://api.openweathermap.org/data/2.5",
"auth_required": true,
"quota_cost": 1
}
POST /api/v1/apis/{api_id}/endpoints/
{
"path": "/weather",
"description": "Current weather by city"
}
POST /api/v1/apis/{api_id}/endpoints/{endpoint_id}/parameters/
{
"name": "q",
"param_type": "query",
"data_type": "STRING",
"required": true,
"description": "City name"
}
POST /api/v1/apis/{api_id}/endpoints/{endpoint_id}/methods/
{ "method": "GET" }
POST /api/v1/apis/{api_id}/endpoints/{endpoint_id}/execute/
{
"method": "GET",
"params": { "q": "Paris" },
"display_format": "standard"
}
Response:
{
"status_code": 200,
"result": "...",
"quota": {
"used": 3,
"remaining": 97,
"limit": 100,
"usage_pct": 3.0
}
}
| Method | URL | Description |
|---|---|---|
| GET | /api/v1/keys/ | List your API keys |
| POST | /api/v1/keys/ | Create a new key |
| DELETE | /api/v1/keys/{id}/ | Revoke a key |
| Method | URL | Description |
|---|---|---|
| GET | /api/v1/quota/ | Current usage + remaining quota |
| GET | /api/v1/limits/ | Platform resource limits |
| Method | URL | Description |
|---|---|---|
| GET | /api/v1/apis/ | List your APIs |
| POST | /api/v1/apis/ | Create an API |
| GET | /api/v1/apis/{id}/ | Get API details |
| PATCH | /api/v1/apis/{id}/ | Update an API |
| DELETE | /api/v1/apis/{id}/ | Delete an API |
All follow the same nested pattern under /api/v1/apis/{api_id}/endpoints/... — see the full reference in the developer documentation at /docs/.
| Method | URL | Description |
|---|---|---|
| POST | /api/v1/apis/{api_id}/endpoints/{endpoint_id}/execute/ | Call the third-party API |
Body:
{
"method": "GET",
"params": { "key": "value" },
"display_format": "json"
}
display_format options: json · compact · standard · verbose
| Method | URL | Description |
|---|---|---|
| GET / POST / PATCH / DELETE | /api/v1/apis/{id}/oauth/ | Manage OAuth config |
| GET | /api/v1/apis/{id}/oauth/token/ | Check token status |
| POST | /api/v1/apis/{id}/oauth/token/ | Force token refresh |
Each user has a monthly credit budget managed by APICallQuota. Each API has a configurable quota_cost (default: 1).
User budget: 100 credits/month
API quota_cost: 5
→ User can make 20 calls to this API per month
Superusers can set monthly_limit = NULL for unlimited access.
| Resource | Default limit |
|---|---|
| APIs per account | 100 |
| Endpoints per API | 10 |
| Parameters per endpoint | 15 |
| Headers per endpoint | 10 |
| API keys per account | 5 |
Applied per API key via DRF throttling:
| Type | Rate |
|---|---|
| Burst | 30 requests / second |
| Sustained | 1000 requests / day |
Exceeded limits return 429 Too Many Requests.
The JSONCleaner engine transforms raw API responses into readable output:
| Format | Description |
|---|---|
json | Raw pretty-printed JSON |
compact | Flat key:value, no emojis |
standard | Human-readable with smart formatting |
verbose | Fully expanded with all nested objects |
| Variable | Description |
|---|---|
DJANGO_SECRET_KEY | Django secret key |
DB_NAME_local | PostgreSQL database name |
DB_USER_local | PostgreSQL user |
DB_PASSWORD_local | PostgreSQL password |
DB_HOST_local | PostgreSQL host |
DB_PORT_local | PostgreSQL port |
MIT — feel free to use, modify, and distribute.
12 commits
Python
92.8%
HTML
7.2%
A self-hosted Outbound API Gateway. Register any third-party API once, call it from a single endpoint. OAuth 2.0, quota management, rate limiting & response formatting. Built with Django + DRF.
See the codeA self-hosted Django platform to manage, proxy, and rate-limit calls to third-party APIs — with OAuth 2.0 support, per-user quota, and a unified REST interface.
Don't want to deploy and maintain the infrastructure yourself? A fully managed SaaS version of Asstgr is available at:
👉 https://www.asstgr.com/home/
It offers a complete management interface:
No need to install PostgreSQL, run Django migrations, or configure a .env file — just create an account and start registering your APIs.
The self-hosted version (this repository) remains available for users who want full control over their infrastructure and data.
Built with Django + DRF. Contributions welcome.
If Asstgr saved you time or gave you ideas, a GitHub star goes a long way — it helps other developers discover the project and keeps me motivated to build more.
⭐ Star it on GitHub — it takes 2 seconds and means a lot. Thank you!
Asstgr is an API Abstraction Layer: instead of integrating third-party APIs directly into your apps, you register them once in Asstgr, describe their endpoints and parameters, and call them through a single, secured interface.
Think of it as your own private RapidAPI — self-hosted, fully programmable via REST, with fine-grained quota control.
Your app ──► Asstgr (/api/v1/...execute/) ──► Stripe / OpenWeatherMap / GitHub / any API
│
├─ Auth (API Key or OAuth2)
├─ Quota enforcement
├─ Request logging
└─ Response formatting
/api/v1/.../execute/ with parametersclient_credentials, authorization_code, and password flows, with automatic token refreshsk-...) to authenticate against Asstgrquota_cost| Layer | Technology |
|---|---|
| Backend | Django 5.x + Django REST Framework |
| Auth | Custom API Key + SimpleJWT + OAuth 2.0 |
| Database | PostgreSQL |
| Async | Daphne / Django Channels (ASGI) |
| Throttling | DRF SimpleRateThrottle |
asstgrv7/
├── asstgrv7/ # Django project (settings, urls, asgi)
│ ├── settings/
│ │ └── dev.py
│ └── urls.py
│
├── api_management/ # Core: API registry, models, OAuth service
│ ├── models.py # API, Endpoint, Parameter, Header, Method, APILog, APICallQuota
│ ├── utils.py # Request building, response formatting (JSONCleaner)
│ ├── oauth_service.py # OAuthService: fetch, refresh, save tokens
│ ├── views_oauth.py # OAuth authorize / callback views
│ └── admin.py
│
├── api_public/ # Public REST API (v1)
│ ├── views.py # All API views (CRUD + Execute + OAuth)
│ ├── models.py # PublicAPIKey
│ ├── serializers.py
│ ├── authentication.py # APIKeyAuthentication
│ ├── permissions.py # IsAPIKeyAuthenticated, HasSufficientQuota
│ ├── throttling.py # Burst + Sustained throttles
│ ├── limits.py # LIMITS constants
│ └── urls.py
│
└── users/ # Custom user model (AbstractUser)
├── models.py
└── admin.py
Asstgr's database is organized around a hierarchy of objects. Here's a quick overview of the core models and their key fields:
APIThe top-level object representing a third-party API.
| Field | Type | Description |
|---|---|---|
name | string | Display name |
url | URL | Base URL of the third-party API |
auth_required | bool | Whether authentication is needed |
quota_cost | int | Credits consumed per call (default: 1) |
is_active / is_blocked | bool | Availability flags |
EndpointA path under an API (e.g. /weather).
| Field | Type | Description |
|---|---|---|
path | string | Path appended to the API base URL |
description | string | What the endpoint does |
example_request / example_response | text | Optional documentation |
ParameterA parameter attached to an endpoint.
| Field | Type | Description |
|---|---|---|
name | string | Parameter name |
param_type | enum | query, path, or body |
data_type | enum | STRING, INTEGER, BOOLEAN, DATE, JSON |
required | bool | Whether the parameter is mandatory |
default_value | string | Optional fallback value |
stored_value | string | Pre-filled value (for non-editable params) |
editable | bool | Whether the caller can override the value |
HeaderA fixed HTTP header sent with every call to an endpoint (e.g. Content-Type, X-Api-Version).
MethodThe HTTP method(s) allowed on an endpoint (GET, POST, PUT, DELETE).
OAuthConfigOAuth 2.0 configuration attached to an API (one per API).
| Field | Description |
|---|---|
grant_type | client_credentials, authorization_code, or password |
token_url | Token endpoint URL |
client_id / client_secret_encrypted | OAuth credentials |
scope | Space-separated scopes |
access_token / refresh_token | Cached token values |
token_expires_at | Expiry datetime (null = permanent token) |
APICallQuotaPer-user monthly credit tracking.
| Field | Description |
|---|---|
monthly_limit | Credit budget (null = unlimited) |
call_count | Credits consumed so far this month |
month / year | Billing period |
APILogAudit record created after every executed call — stores the user, endpoint, HTTP method, request/response data, status code, and response size.
git clone https://github.com/asstgr/asstgropensource.git
cd asstgropensource
python -m venv venv && source venv/bin/activate
pip install -r requirements.txt
Create a .env file at the project root:
DJANGO_SECRET_KEY=your-secret-key
DB_NAME_local=asstgr_db
DB_USER_local=postgres
DB_PASSWORD_local=your-password
DB_HOST_local=localhost
DB_PORT_local=5432
python manage.py migrate --settings=asstgrv7.settings.dev
python manage.py createsuperuser --settings=asstgrv7.settings.dev
python manage.py runserver --settings=asstgrv7.settings.dev
The API is available at http://localhost:8000/api/v1/.
All requests to /api/v1/ must include your API key:
Authorization: Api-Key sk-xxxxxxxxxxxxxxxxxxxxxxxx
Generate a key from the admin panel or via:
POST /api/v1/keys/
Content-Type: application/json
{ "name": "My production key" }
POST /api/v1/apis/
{
"name": "OpenWeatherMap",
"url": "https://api.openweathermap.org/data/2.5",
"auth_required": true,
"quota_cost": 1
}
POST /api/v1/apis/{api_id}/endpoints/
{
"path": "/weather",
"description": "Current weather by city"
}
POST /api/v1/apis/{api_id}/endpoints/{endpoint_id}/parameters/
{
"name": "q",
"param_type": "query",
"data_type": "STRING",
"required": true,
"description": "City name"
}
POST /api/v1/apis/{api_id}/endpoints/{endpoint_id}/methods/
{ "method": "GET" }
POST /api/v1/apis/{api_id}/endpoints/{endpoint_id}/execute/
{
"method": "GET",
"params": { "q": "Paris" },
"display_format": "standard"
}
Response:
{
"status_code": 200,
"result": "...",
"quota": {
"used": 3,
"remaining": 97,
"limit": 100,
"usage_pct": 3.0
}
}
| Method | URL | Description |
|---|---|---|
| GET | /api/v1/keys/ | List your API keys |
| POST | /api/v1/keys/ | Create a new key |
| DELETE | /api/v1/keys/{id}/ | Revoke a key |
| Method | URL | Description |
|---|---|---|
| GET | /api/v1/quota/ | Current usage + remaining quota |
| GET | /api/v1/limits/ | Platform resource limits |
| Method | URL | Description |
|---|---|---|
| GET | /api/v1/apis/ | List your APIs |
| POST | /api/v1/apis/ | Create an API |
| GET | /api/v1/apis/{id}/ | Get API details |
| PATCH | /api/v1/apis/{id}/ | Update an API |
| DELETE | /api/v1/apis/{id}/ | Delete an API |
All follow the same nested pattern under /api/v1/apis/{api_id}/endpoints/... — see the full reference in the developer documentation at /docs/.
| Method | URL | Description |
|---|---|---|
| POST | /api/v1/apis/{api_id}/endpoints/{endpoint_id}/execute/ | Call the third-party API |
Body:
{
"method": "GET",
"params": { "key": "value" },
"display_format": "json"
}
display_format options: json · compact · standard · verbose
| Method | URL | Description |
|---|---|---|
| GET / POST / PATCH / DELETE | /api/v1/apis/{id}/oauth/ | Manage OAuth config |
| GET | /api/v1/apis/{id}/oauth/token/ | Check token status |
| POST | /api/v1/apis/{id}/oauth/token/ | Force token refresh |
Each user has a monthly credit budget managed by APICallQuota. Each API has a configurable quota_cost (default: 1).
User budget: 100 credits/month
API quota_cost: 5
→ User can make 20 calls to this API per month
Superusers can set monthly_limit = NULL for unlimited access.
| Resource | Default limit |
|---|---|
| APIs per account | 100 |
| Endpoints per API | 10 |
| Parameters per endpoint | 15 |
| Headers per endpoint | 10 |
| API keys per account | 5 |
Applied per API key via DRF throttling:
| Type | Rate |
|---|---|
| Burst | 30 requests / second |
| Sustained | 1000 requests / day |
Exceeded limits return 429 Too Many Requests.
The JSONCleaner engine transforms raw API responses into readable output:
| Format | Description |
|---|---|
json | Raw pretty-printed JSON |
compact | Flat key:value, no emojis |
standard | Human-readable with smart formatting |
verbose | Fully expanded with all nested objects |
| Variable | Description |
|---|---|
DJANGO_SECRET_KEY | Django secret key |
DB_NAME_local | PostgreSQL database name |
DB_USER_local | PostgreSQL user |
DB_PASSWORD_local | PostgreSQL password |
DB_HOST_local | PostgreSQL host |
DB_PORT_local | PostgreSQL port |
MIT — feel free to use, modify, and distribute.
12 commits
Python
92.8%
HTML
7.2%