How to Use the AxonHub GraphQL API for Management Operations
AxonHub exposes a single GraphQL endpoint at /openapi/v1/graphql that provides type-safe, RBAC-protected management operations for channels, API keys, users, roles, and projects, implemented via gqlgen and wired into the Gin HTTP server.
The looplj/axonhub repository provides a comprehensive management interface through its GraphQL API. This endpoint allows administrators to programmatically control every aspect of the platform, from provisioning AI model channels to managing user permissions, all through a strongly-typed schema defined in the source code.
Architecture of the GraphQL Management API
GraphQL Schema Definition
All public mutations and queries live in internal/server/gql/axonhub.graphql. The type Mutation definition lists every management operation, including createChannel, bulkCreateChannels, deleteChannel, disableChannelAPIKey, createUser, and updateProject. These definitions enforce input validation and type safety at the API boundary.
Source: internal/server/gql/axonhub.graphql
Resolver Implementation
Each schema field is backed by a resolver in internal/server/gql/axonhub.resolvers.go. These resolvers act as the bridge between the GraphQL layer and the business logic. For example, the CreateChannel resolver calls r.channelService.CreateChannel to persist the new channel and returns the result to the client.
Source: [internal/server/gql/axonhub.resolvers.go](https://github.com/looplj/axonhub/blob/unstable/internal/server/gql/axonhub.resolvers.go)
Business Logic Layer
The core operations are implemented in the internal/server/biz/ directory. Services such as ChannelService, APIKeyService, UserService, and ProjectService handle validation, database persistence via Ent, and side effects.
Sources:
- Channel: [
internal/server/biz/channel.go](https://github.com/looplj/axonhub/blob/unstable/internal/server/biz/channel.go) - API key: [
internal/server/biz/apikey.go](https://github.com/looplj/axonhub/blob/unstable/internal/server/biz/apikey.go) - User/role/project services:
internal/server/biz/user.go,internal/server/biz/role.go,internal/server/biz/project.go
Authentication and Authorization
Management calls require a valid JWT. Users obtain a token via the POST /auth/signin HTTP route, handled by internal/server/api/auth.go. The token must be sent as an Authorization: Bearer <token> header on every GraphQL request. The Gin router applies middleware to enforce this protection.
Sources:
- Route definition: [
internal/server/routes.go](https://github.com/looplj/axonhub/blob/unstable/internal/server/routes.go) - Handler: [
internal/server/api/auth.go](https://github.com/looplj/axonhub/blob/unstable/internal/server/api/auth.go)
GraphQL Endpoint and Authentication
The management GraphQL API is exposed at /openapi/v1/graphql. All requests must include a Bearer token in the Authorization header.
First, obtain a JWT token:
curl -X POST http://localhost:8090/auth/signin \
-H "Content-Type: application/json" \
-d '{"email":"admin@example.com","password":"your‑password"}'
The response contains:
{
"user": { "id": 1, "email": "admin@example.com" },
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Management Operations Examples
Creating a Channel
Use the createChannel mutation to provision a new AI model channel. This delegates to the channel service in internal/server/biz/channel.go.
TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI…"
curl -X POST http://localhost:8090/openapi/v1/graphql \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{
"query": "mutation CreateChannel($input: CreateChannelInput!) { createChannel(input: $input) { id name type status } }",
"variables": {
"input": {
"type": "OPENAI",
"name": "my-openai-channel",
"tags": ["production"],
"baseURL": "https://api.openai.com/v1",
"apiKeys": ["sk-xxxx"],
"supportedModels": ["gpt-4o"],
"defaultTestModel": "gpt-4o"
}
}
}'
Disabling a Channel API Key
To revoke a specific key without deleting the channel, use the disableChannelAPIKey mutation implemented in the resolvers.
curl -X POST http://localhost:8090/openapi/v1/graphql \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{
"query": "mutation($channelID: ID!, $key: String!){disableChannelAPIKey(channelID: $channelID, key: $key)}",
"variables": {
"channelID": "1",
"key": "sk-xxxx"
}
}'
Managing Users and Projects
Similar patterns apply to user and project management. The createUser, updateProject, and related mutations follow the same resolver → service → database flow. Refer to internal/server/biz/user.go and internal/server/biz/project.go for the underlying business logic.
Type-Safe Go Client with GenQLient
For production Go applications, use genqlient to generate a type-safe client from the schema.
First, install the tool and generate the client:
go install github.com/Khan/genqlient@latest
genqlient generate ./internal/server/gql/...
Then use the generated code:
package main
import (
"context"
"log"
"os"
"github.com/Khan/genqlient/graphql"
"your/module/internal/server/gql/genqlient"
)
func main() {
token := os.Getenv("AXONHUB_TOKEN")
httpClient := graphql.NewHTTPClient(
"http://localhost:8090/openapi/v1/graphql",
graphql.WithHeader("Authorization", "Bearer "+token),
)
ctx := context.Background()
resp, err := genqlient.CreateChannel(ctx, httpClient, genqlient.CreateChannelInput{
Type: genqlient.ChannelTypeOpenAI,
Name: "go-client-channel",
Tags: []string{"automated"},
BaseURL: "https://api.openai.com/v1",
APIKeys: []string{"sk-xxxx"},
SupportedModels: []string{"gpt-4o-mini"},
DefaultTestModel: "gpt-4o-mini",
})
if err != nil {
log.Fatalf("createChannel failed: %v", err)
}
log.Printf("Created channel ID: %s", resp.ID)
}
Key Source Files
Summary
- AxonHub exposes a single GraphQL API endpoint at
/openapi/v1/graphqlfor all management operations. - The schema is defined in
axonhub.graphqland implemented by resolvers inaxonhub.resolvers.go, which delegate to business services ininternal/server/biz/. - Authentication requires a JWT obtained from
POST /auth/signinand passed as a Bearer token. - You can interact with the API using raw cURL commands or generate a type-safe Go client using genqlient.
- Key operations include creating channels, disabling API keys, managing users, and configuring projects.
Frequently Asked Questions
What is the AxonHub GraphQL endpoint URL for management operations?
The management GraphQL API is available at /openapi/v1/graphql relative to your AxonHub base URL (e.g., http://localhost:8090/openapi/v1/graphql). This single endpoint handles all administrative queries and mutations, including channel provisioning, user management, and API key rotation, as defined in the schema file internal/server/gql/axonhub.graphql.
How do I authenticate requests to the GraphQL API?
All management calls require a valid JWT token. First, authenticate via the REST endpoint POST /auth/signin (implemented in [internal/server/api/auth.go](https://github.com/looplj/axonhub/blob/unstable/internal/server/api/auth.go)) with your email and password. The response returns a token string that you must include in the Authorization: Bearer <token> header on every GraphQL request. The Gin router enforces this protection in [internal/server/routes.go](https://github.com/looplj/axonhub/blob/unstable/internal/server/routes.go).
Can I use a type-safe client instead of raw HTTP requests?
Yes. AxonHub's GraphQL schema is compatible with genqlient, a Go code generator for GraphQL. By running genqlient generate against internal/server/gql/axonhub.graphql, you produce a type-safe client that validates queries at compile time. This eliminates manual JSON construction and reduces runtime errors when calling management operations like createChannel or disableChannelAPIKey.
Where are the GraphQL resolvers for management operations implemented?
The resolver functions that bridge the GraphQL API to the business layer are located in [internal/server/gql/axonhub.resolvers.go](https://github.com/looplj/axonhub/blob/unstable/internal/server/gql/axonhub.resolvers.go). Each mutation (such as createChannel, disableChannelAPIKey, or createUser) has a corresponding resolver method that validates inputs, invokes the appropriate service in internal/server/biz/, and returns the result to the GraphQL layer.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →