Internal API Reference
Version: 1.0.0
Base URL: http://core:8000
This document describes the internal API endpoints used for service-to-service communication.
Authentication
All internal API endpoints require the X-Notifito-Internal-Secret header.
X-Notifito-Internal-Secret: your-internal-secret
This secret is shared between services and configured via the INTERNAL_SECRET environment variable.
Auth Endpoints
Login
Authenticates a seller user and returns tenant information.
Endpoint: POST /internal/auth/login
Authentication: Internal secret
Request Body
{
"email": "owner@sneaker-store.test",
"password": "password"
}
| Field | Type | Required | Description |
|---|---|---|---|
email |
string | Yes | User email address |
password |
string | Yes | User password |
Response
200 OK
{
"user": {
"id": "user-123",
"name": "Owner",
"email": "owner@sneaker-store.test"
},
"tenant": {
"id": "ten-456",
"name": "Sneaker Store",
"slug": "sneaker-store",
"timezone": "UTC",
"domains": ["shop.test"]
}
}
401 Unauthorized
{
"message": "These credentials do not match our records."
}
Examples
cURL
curl -X POST "http://core:8000/internal/auth/login" \
-H "X-Notifito-Internal-Secret: your-secret" \
-H "Content-Type: application/json" \
-d '{
"email": "owner@sneaker-store.test",
"password": "password"
}'
PHP
use Illuminate\Support\Facades\Http;
$response = Http::withHeaders([
'X-Notifito-Internal-Secret' => config('notifito.internal_secret'),
])->post('http://core:8000/internal/auth/login', [
'email' => 'owner@sneaker-store.test',
'password' => 'password',
]);
$result = $response->json();
Item Type Endpoints
List Item Types
Returns all item types for a tenant.
Endpoint: GET /internal/tenants/{tenant}/item-types
Authentication: Internal secret
Parameters
| Parameter | Type | Location | Description |
|---|---|---|---|
tenant |
string | path | Tenant UUID |
Response
200 OK
{
"item_types": [
{
"id": "it-123",
"name": "Sneaker",
"slug": "sneaker",
"schema_version": 1,
"attribute_count": 1,
"item_count": 2
}
]
}
Examples
cURL
curl "http://core:8000/internal/tenants/ten-456/item-types" \
-H "X-Notifito-Internal-Secret: your-secret"
PHP
use Illuminate\Support\Facades\Http;
$response = Http::withHeaders([
'X-Notifito-Internal-Secret' => config('notifito.internal_secret'),
])->get("http://core:8000/internal/tenants/{$tenantId}/item-types");
$itemTypes = $response->json('item_types');
Get Item Type
Returns a specific item type with its schema and items.
Endpoint: GET /internal/tenants/{tenant}/item-types/{itemType}
Authentication: Internal secret
Parameters
| Parameter | Type | Location | Description |
|---|---|---|---|
tenant |
string | path | Tenant UUID |
itemType |
string | path | Item type UUID or slug |
Response
200 OK
{
"id": "it-123",
"name": "Sneaker",
"slug": "sneaker",
"schema_version": 1,
"attribute_schema": [
{
"key": "size",
"label": "Size",
"type": "enum",
"options": ["40", "41", "42"],
"required": true,
"matchable": true,
"multiple": false
}
],
"notify_policy": "all",
"notify_factor": 3,
"subscription_mode": "once",
"action_url_template": null,
"items": [
{
"id": "item-789",
"name": "Air Max 90",
"external_ref": "SKU-AM90"
}
]
}
404 Not Found
{
"message": "Unknown item type."
}
Create/Update Item Type
Creates a new item type or updates an existing one.
Endpoint: POST /internal/tenants/{tenant}/item-types
Authentication: Internal secret
Parameters
| Parameter | Type | Location | Description |
|---|---|---|---|
tenant |
string | path | Tenant UUID |
Request Body
{
"id": null,
"name": "Sneaker",
"slug": "sneaker",
"attribute_schema": [
{
"key": "size",
"label": "Size",
"type": "enum",
"options": ["40", "41", "42"],
"required": true,
"matchable": true,
"multiple": false
}
],
"notify_policy": "all",
"notify_factor": 3,
"subscription_mode": "once",
"action_url_template": null
}
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | No | Item type UUID (for updates) |
name |
string | Yes | Display name |
slug |
string | Yes | URL-friendly identifier |
attribute_schema |
array | Yes | Attribute definitions |
notify_policy |
string | Yes | all or capacity_multiple |
notify_factor |
integer | Yes | Capacity multiplier |
subscription_mode |
string | Yes | once or recurring |
action_url_template |
string | No | URL template |
Response
200 OK
{
"id": "it-123",
"schema_version": 1
}
422 Unprocessable Entity
{
"errors": {
"attribute_schema": ["Attribute key [Bad Key] must be lowercase snake_case"]
}
}
Examples
cURL
curl -X POST "http://core:8000/internal/tenants/ten-456/item-types" \
-H "X-Notifito-Internal-Secret: your-secret" \
-H "Content-Type: application/json" \
-d '{
"name": "Sneaker",
"slug": "sneaker",
"attribute_schema": [
{
"key": "size",
"label": "Size",
"type": "enum",
"options": ["40", "41", "42"],
"required": true,
"matchable": true,
"multiple": false
}
],
"notify_policy": "all",
"notify_factor": 3,
"subscription_mode": "once"
}'
PHP
use Illuminate\Support\Facades\Http;
$response = Http::withHeaders([
'X-Notifito-Internal-Secret' => config('notifito.internal_secret'),
])->post("http://core:8000/internal/tenants/{$tenantId}/item-types", [
'name' => 'Sneaker',
'slug' => 'sneaker',
'attribute_schema' => [
[
'key' => 'size',
'label' => 'Size',
'type' => 'enum',
'options' => ['40', '41', '42'],
'required' => true,
'matchable' => true,
'multiple' => false,
],
],
'notify_policy' => 'all',
'notify_factor' => 3,
'subscription_mode' => 'once',
]);
$result = $response->json();
Subscription Endpoints
Create Subscription
Creates a new subscription (used by edge).
Endpoint: POST /internal/subscriptions
Authentication: Internal secret
Request Body
{
"tenant_id": "ten-456",
"item_type_id": "it-123",
"item_id": null,
"attributes": {
"size": "42"
},
"channel": "email",
"contact_value": "consumer@example.com",
"source": "widget",
"ip": "203.0.113.7",
"user_agent": "Mozilla/5.0",
"correlation_id": "corr-abc"
}
Response
202 Accepted
{
"subscription_id": "sub-123",
"was_created": true,
"confirmation_sent": true
}
422 Unprocessable Entity
{
"message": "The given data was invalid.",
"errors": {
"attributes.size": ["Size must be one of: 40, 41, 42."]
}
}
Confirm Subscription
Confirms a subscription via token.
Endpoint: POST /internal/subscriptions/confirm
Authentication: Internal secret
Request Body
{
"token": "confirmation-token-32-chars",
"ip": "203.0.113.7",
"user_agent": "Mozilla/5.0"
}
Response
200 OK
{
"status": "active"
}
422 Unprocessable Entity
{
"message": "Invalid or expired token.",
"status": "invalid_token"
}
Unsubscribe
Unsubscribes via token.
Endpoint: POST /internal/subscriptions/unsubscribe
Authentication: Internal secret
Request Body
{
"token": "unsubscribe-token-32-chars",
"ip": "203.0.113.7",
"user_agent": "Mozilla/5.0"
}
Response
200 OK
{
"status": "unsubscribed"
}
Key Management Endpoints
Get Dashboard Key
Returns or creates a dashboard secret key for a tenant.
Endpoint: POST /internal/tenants/{tenant}/keys/dashboard
Authentication: Internal secret
Parameters
| Parameter | Type | Location | Description |
|---|---|---|---|
tenant |
string | path | Tenant UUID |
Response
200 OK
{
"key": "sk_live_dashboardkey0000000"
}
404 Not Found
{
"message": "No query results for model [App\\Models\\Tenant]."
}
Examples
cURL
curl -X POST "http://core:8000/internal/tenants/ten-456/keys/dashboard" \
-H "X-Notifito-Internal-Secret: your-secret"
PHP
use Illuminate\Support\Facades\Http;
$response = Http::withHeaders([
'X-Notifito-Internal-Secret' => config('notifito.internal_secret'),
])->post("http://core:8000/internal/tenants/{$tenantId}/keys/dashboard");
$key = $response->json('key');
Key Resolution Endpoint
Resolve API Key
Resolves a publishable key to its tenant context.
Endpoint: POST /internal/keys/resolve
Authentication: Internal secret
Request Body
{
"key": "pk_live_ADbaCjvo5TT1x8104zHXKSHr"
}
Response
200 OK
{
"tenant_id": "ten-456",
"tenant_name": "Sneaker Store",
"tenant_slug": "sneaker-store",
"tenant_domains": ["shop.test"]
}
404 Not Found
{
"message": "Unknown API key."
}
Error Responses
All errors follow a consistent format:
{
"message": "Human-readable error message",
"errors": {
"field": ["Validation error message"]
}
}
HTTP Status Codes
| Code | Meaning |
|---|---|
| 200 | Success |
| 202 | Accepted |
| 401 | Unauthorized (missing or invalid internal secret) |
| 404 | Not Found |
| 422 | Validation Error |
| 500 | Internal Server Error |
Related Documentation
- Edge API — Public API endpoints
- Architecture Overview — System design
- Configuration Reference — Environment variables