Update documentation structure and enhance .gitignore
- Added generated index files and report directories to .gitignore to prevent unnecessary tracking of transient files. - Updated README links to reflect new documentation paths for better navigation. - Improved documentation organization by ensuring all links point to the correct locations, enhancing user experience and accessibility.
This commit is contained in:
680
docs/api/API_DOCUMENTATION.md
Normal file
680
docs/api/API_DOCUMENTATION.md
Normal file
@@ -0,0 +1,680 @@
|
||||
# API Documentation
|
||||
|
||||
Complete GraphQL API documentation for Sankofa Phoenix.
|
||||
|
||||
## Base URL
|
||||
|
||||
- **Production**: `https://api.sankofa.nexus/graphql`
|
||||
- **Development**: `http://localhost:4000/graphql`
|
||||
|
||||
## Authentication
|
||||
|
||||
All requests (except health check) require authentication via JWT token:
|
||||
|
||||
```http
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
Tokens are obtained via Keycloak OIDC authentication.
|
||||
|
||||
## Queries
|
||||
|
||||
### Health Check
|
||||
|
||||
Check API health status.
|
||||
|
||||
```graphql
|
||||
query {
|
||||
health {
|
||||
status
|
||||
timestamp
|
||||
version
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"health": {
|
||||
"status": "ok",
|
||||
"timestamp": "2024-01-01T00:00:00Z",
|
||||
"version": "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Resources
|
||||
|
||||
Query resources with optional filtering.
|
||||
|
||||
```graphql
|
||||
query {
|
||||
resources(filter: {
|
||||
type: VM
|
||||
status: RUNNING
|
||||
siteId: "site-1"
|
||||
}) {
|
||||
id
|
||||
name
|
||||
type
|
||||
status
|
||||
site {
|
||||
id
|
||||
name
|
||||
region
|
||||
}
|
||||
metadata
|
||||
createdAt
|
||||
updatedAt
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Filter Options:**
|
||||
- `type`: Resource type (VM, CONTAINER, STORAGE, NETWORK)
|
||||
- `status`: Resource status (RUNNING, STOPPED, PENDING, ERROR)
|
||||
- `siteId`: Filter by site ID
|
||||
- `tenantId`: Filter by tenant ID (admin only)
|
||||
|
||||
### Resource
|
||||
|
||||
Get a single resource by ID.
|
||||
|
||||
```graphql
|
||||
query {
|
||||
resource(id: "resource-id") {
|
||||
id
|
||||
name
|
||||
type
|
||||
status
|
||||
site {
|
||||
id
|
||||
name
|
||||
}
|
||||
metadata
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Sites
|
||||
|
||||
List all accessible sites.
|
||||
|
||||
```graphql
|
||||
query {
|
||||
sites {
|
||||
id
|
||||
name
|
||||
region
|
||||
status
|
||||
metadata
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Tenants
|
||||
|
||||
List all tenants (admin only).
|
||||
|
||||
```graphql
|
||||
query {
|
||||
tenants {
|
||||
id
|
||||
name
|
||||
domain
|
||||
status
|
||||
tier
|
||||
quotaLimits {
|
||||
compute {
|
||||
vcpu
|
||||
memory
|
||||
instances
|
||||
}
|
||||
storage {
|
||||
total
|
||||
}
|
||||
}
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Tenant
|
||||
|
||||
Get tenant details.
|
||||
|
||||
```graphql
|
||||
query {
|
||||
tenant(id: "tenant-id") {
|
||||
id
|
||||
name
|
||||
status
|
||||
resources {
|
||||
id
|
||||
name
|
||||
type
|
||||
}
|
||||
usage {
|
||||
totalCost
|
||||
byResource {
|
||||
resourceId
|
||||
cost
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Usage Report
|
||||
|
||||
Get usage report for a tenant.
|
||||
|
||||
```graphql
|
||||
query {
|
||||
usage(
|
||||
tenantId: "tenant-id"
|
||||
timeRange: {
|
||||
start: "2024-01-01T00:00:00Z"
|
||||
end: "2024-01-31T23:59:59Z"
|
||||
}
|
||||
granularity: DAY
|
||||
) {
|
||||
totalCost
|
||||
currency
|
||||
byResource {
|
||||
resourceId
|
||||
resourceName
|
||||
cost
|
||||
quantity
|
||||
}
|
||||
byMetric {
|
||||
metricType
|
||||
cost
|
||||
quantity
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Invoices
|
||||
|
||||
List invoices for a tenant.
|
||||
|
||||
```graphql
|
||||
query {
|
||||
invoices(
|
||||
tenantId: "tenant-id"
|
||||
filter: {
|
||||
status: PAID
|
||||
startDate: "2024-01-01"
|
||||
endDate: "2024-01-31"
|
||||
}
|
||||
) {
|
||||
invoices {
|
||||
id
|
||||
invoiceNumber
|
||||
billingPeriodStart
|
||||
billingPeriodEnd
|
||||
total
|
||||
currency
|
||||
status
|
||||
lineItems {
|
||||
description
|
||||
quantity
|
||||
unitPrice
|
||||
total
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Budgets
|
||||
|
||||
Get budgets for a tenant.
|
||||
|
||||
```graphql
|
||||
query {
|
||||
budgets(tenantId: "tenant-id") {
|
||||
id
|
||||
name
|
||||
amount
|
||||
currency
|
||||
period
|
||||
currentSpend
|
||||
remaining
|
||||
alertThresholds
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Billing Alerts
|
||||
|
||||
Get billing alerts for a tenant.
|
||||
|
||||
```graphql
|
||||
query {
|
||||
billingAlerts(tenantId: "tenant-id") {
|
||||
id
|
||||
name
|
||||
alertType
|
||||
threshold
|
||||
enabled
|
||||
lastTriggeredAt
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Mutations
|
||||
|
||||
### Create Resource
|
||||
|
||||
Create a new resource.
|
||||
|
||||
```graphql
|
||||
mutation {
|
||||
createResource(input: {
|
||||
name: "my-vm"
|
||||
type: VM
|
||||
siteId: "site-1"
|
||||
metadata: {
|
||||
cpu: 4
|
||||
memory: "8Gi"
|
||||
disk: "100Gi"
|
||||
}
|
||||
}) {
|
||||
id
|
||||
name
|
||||
status
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Update Resource
|
||||
|
||||
Update an existing resource.
|
||||
|
||||
```graphql
|
||||
mutation {
|
||||
updateResource(
|
||||
id: "resource-id"
|
||||
input: {
|
||||
name: "updated-name"
|
||||
metadata: {
|
||||
cpu: 8
|
||||
}
|
||||
}
|
||||
) {
|
||||
id
|
||||
name
|
||||
metadata
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Delete Resource
|
||||
|
||||
Delete a resource.
|
||||
|
||||
```graphql
|
||||
mutation {
|
||||
deleteResource(id: "resource-id")
|
||||
}
|
||||
```
|
||||
|
||||
### Create Tenant
|
||||
|
||||
Create a new tenant (admin only).
|
||||
|
||||
```graphql
|
||||
mutation {
|
||||
createTenant(input: {
|
||||
name: "New Tenant"
|
||||
domain: "tenant.example.com"
|
||||
tier: STANDARD
|
||||
quotaLimits: {
|
||||
compute: {
|
||||
vcpu: 16
|
||||
memory: 64
|
||||
instances: 10
|
||||
}
|
||||
storage: {
|
||||
total: 1000
|
||||
}
|
||||
}
|
||||
}) {
|
||||
id
|
||||
name
|
||||
status
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Share Resource Across Tenants
|
||||
|
||||
Share a resource with other tenants.
|
||||
|
||||
```graphql
|
||||
mutation {
|
||||
shareResourceAcrossTenants(
|
||||
resourceId: "resource-id"
|
||||
sourceTenantId: "tenant-1"
|
||||
targetTenants: ["tenant-2", "tenant-3"]
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Create Invoice
|
||||
|
||||
Generate an invoice for a tenant (admin only).
|
||||
|
||||
```graphql
|
||||
mutation {
|
||||
createInvoice(
|
||||
tenantId: "tenant-id"
|
||||
billingPeriodStart: "2024-01-01T00:00:00Z"
|
||||
billingPeriodEnd: "2024-01-31T23:59:59Z"
|
||||
) {
|
||||
id
|
||||
invoiceNumber
|
||||
total
|
||||
status
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Create Budget
|
||||
|
||||
Create a budget for a tenant.
|
||||
|
||||
```graphql
|
||||
mutation {
|
||||
createBudget(
|
||||
tenantId: "tenant-id"
|
||||
budget: {
|
||||
name: "Monthly Budget"
|
||||
amount: 1000
|
||||
currency: USD
|
||||
period: MONTHLY
|
||||
startDate: "2024-01-01T00:00:00Z"
|
||||
alertThresholds: [0.5, 0.75, 0.9]
|
||||
}
|
||||
) {
|
||||
id
|
||||
name
|
||||
amount
|
||||
currentSpend
|
||||
remaining
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Create Billing Alert
|
||||
|
||||
Create a billing alert.
|
||||
|
||||
```graphql
|
||||
mutation {
|
||||
createBillingAlert(
|
||||
tenantId: "tenant-id"
|
||||
alert: {
|
||||
name: "Budget Warning"
|
||||
alertType: BUDGET
|
||||
threshold: 0.8
|
||||
condition: {
|
||||
budgetId: "budget-id"
|
||||
}
|
||||
}
|
||||
) {
|
||||
id
|
||||
name
|
||||
enabled
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
All errors follow GraphQL error format:
|
||||
|
||||
```json
|
||||
{
|
||||
"errors": [
|
||||
{
|
||||
"message": "Error message",
|
||||
"extensions": {
|
||||
"code": "ERROR_CODE",
|
||||
"field": "fieldName"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Error Codes
|
||||
|
||||
- `UNAUTHENTICATED`: Authentication required
|
||||
- `FORBIDDEN`: Insufficient permissions
|
||||
- `NOT_FOUND`: Resource not found
|
||||
- `VALIDATION_ERROR`: Input validation failed
|
||||
- `INTERNAL_ERROR`: Server error
|
||||
- `QUOTA_EXCEEDED`: Tenant quota exceeded
|
||||
|
||||
## Rate Limiting
|
||||
|
||||
- **Default**: 100 requests per minute per user
|
||||
- **Admin**: 1000 requests per minute
|
||||
- **Service Accounts**: 5000 requests per minute
|
||||
|
||||
Rate limit headers:
|
||||
```
|
||||
X-RateLimit-Limit: 100
|
||||
X-RateLimit-Remaining: 95
|
||||
X-RateLimit-Reset: 1640995200
|
||||
```
|
||||
|
||||
## Pagination
|
||||
|
||||
List queries support pagination:
|
||||
|
||||
```graphql
|
||||
query {
|
||||
resources(filter: {}, limit: 10, offset: 0) {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Subscriptions
|
||||
|
||||
Real-time updates via GraphQL subscriptions:
|
||||
|
||||
```graphql
|
||||
subscription {
|
||||
resourceUpdated(resourceId: "resource-id") {
|
||||
id
|
||||
status
|
||||
metadata
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Available subscriptions:
|
||||
- `resourceCreated`
|
||||
- `resourceUpdated`
|
||||
- `resourceDeleted`
|
||||
- `billingAlertTriggered`
|
||||
- `incidentDetected`
|
||||
|
||||
## Examples
|
||||
|
||||
### Complete Resource Lifecycle
|
||||
|
||||
```graphql
|
||||
# 1. Create resource
|
||||
mutation {
|
||||
createResource(input: {
|
||||
name: "web-server"
|
||||
type: VM
|
||||
siteId: "site-1"
|
||||
metadata: { cpu: 4, memory: "8Gi" }
|
||||
}) {
|
||||
id
|
||||
status
|
||||
}
|
||||
}
|
||||
|
||||
# 2. Query resource
|
||||
query {
|
||||
resource(id: "resource-id") {
|
||||
id
|
||||
name
|
||||
status
|
||||
site {
|
||||
name
|
||||
region
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# 3. Update resource
|
||||
mutation {
|
||||
updateResource(
|
||||
id: "resource-id"
|
||||
input: { metadata: { cpu: 8 } }
|
||||
) {
|
||||
id
|
||||
metadata
|
||||
}
|
||||
}
|
||||
|
||||
# 4. Delete resource
|
||||
mutation {
|
||||
deleteResource(id: "resource-id")
|
||||
}
|
||||
```
|
||||
|
||||
### Billing Workflow
|
||||
|
||||
```graphql
|
||||
# 1. Check usage
|
||||
query {
|
||||
usage(
|
||||
tenantId: "tenant-id"
|
||||
timeRange: { start: "...", end: "..." }
|
||||
granularity: DAY
|
||||
) {
|
||||
totalCost
|
||||
byResource {
|
||||
resourceId
|
||||
cost
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# 2. Create budget
|
||||
mutation {
|
||||
createBudget(
|
||||
tenantId: "tenant-id"
|
||||
budget: {
|
||||
name: "Monthly"
|
||||
amount: 1000
|
||||
period: MONTHLY
|
||||
}
|
||||
) {
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
# 3. Create alert
|
||||
mutation {
|
||||
createBillingAlert(
|
||||
tenantId: "tenant-id"
|
||||
alert: {
|
||||
name: "Budget Warning"
|
||||
alertType: BUDGET
|
||||
threshold: 0.8
|
||||
}
|
||||
) {
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
# 4. Generate invoice
|
||||
mutation {
|
||||
createInvoice(
|
||||
tenantId: "tenant-id"
|
||||
billingPeriodStart: "..."
|
||||
billingPeriodEnd: "..."
|
||||
) {
|
||||
id
|
||||
invoiceNumber
|
||||
total
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## SDK Examples
|
||||
|
||||
### JavaScript/TypeScript
|
||||
|
||||
```typescript
|
||||
import { ApolloClient, InMemoryCache, gql } from '@apollo/client'
|
||||
|
||||
const client = new ApolloClient({
|
||||
uri: 'https://api.sankofa.nexus/graphql',
|
||||
cache: new InMemoryCache(),
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`
|
||||
}
|
||||
})
|
||||
|
||||
const GET_RESOURCES = gql`
|
||||
query {
|
||||
resources {
|
||||
id
|
||||
name
|
||||
type
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const { data } = await client.query({ query: GET_RESOURCES })
|
||||
```
|
||||
|
||||
### Python
|
||||
|
||||
```python
|
||||
from gql import gql, Client
|
||||
from gql.transport.requests import RequestsHTTPTransport
|
||||
|
||||
transport = RequestsHTTPTransport(
|
||||
url="https://api.sankofa.nexus/graphql",
|
||||
headers={"Authorization": f"Bearer {token}"}
|
||||
)
|
||||
|
||||
client = Client(transport=transport, fetch_schema_from_transport=True)
|
||||
|
||||
query = gql("""
|
||||
query {
|
||||
resources {
|
||||
id
|
||||
name
|
||||
type
|
||||
}
|
||||
}
|
||||
""")
|
||||
|
||||
result = client.execute(query)
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- GraphQL Specification: https://graphql.org/learn/
|
||||
- Apollo Server: https://www.apollographql.com/docs/apollo-server/
|
||||
- Schema Definition: `api/src/schema/typeDefs.ts`
|
||||
|
||||
Reference in New Issue
Block a user