Skip to content

REST API

Goiabada provides REST APIs for programmatic management of users, groups, clients, and settings. These APIs are used internally by the admin console but can also be called directly from your applications.

The auth server exposes two main API groups:

APIRequired ScopePurpose
Admin API
/api/v1/admin
authserver:manage (or granular scopes)Administrative control
Account API
/api/v1/account
authserver:manage-accountSelf-service account management

Instead of granting full admin access with authserver:manage, you can use granular scopes to limit access to specific API domains:

ScopeAccess LevelEndpoints
authserver:admin-readRead-onlyGET requests across all admin endpoints
authserver:manage-usersFullUsers, groups, permissions, sessions, consents
authserver:manage-clientsFullOAuth2 clients and their configurations
authserver:manage-settingsFullSystem settings, resources, and signing keys
authserver:manageFullAll admin endpoints (backwards compatible)
  • Read operations (GET): Allowed by authserver:admin-read, the domain-specific scope, or authserver:manage
  • Write operations (POST, PUT, DELETE): Require the domain-specific scope or authserver:manage

For example, to read user data you need any of:

  • authserver:admin-read
  • authserver:manage-users
  • authserver:manage

But to create or update a user, you need:

  • authserver:manage-users
  • authserver:manage

All API endpoints require a valid JWT access token in the Authorization header:

Authorization: Bearer <access_token>

Before you can call the REST APIs, you need to create a dedicated client and assign the appropriate permissions:

  1. Log into the admin console
  2. Navigate to Clients and click Create new
  3. Configure the client:
    • Client identifier: Choose a meaningful name (e.g., api-client)
    • Description: Describe the purpose (e.g., “Client for REST API access”)
    • Enabled flow: Enable only Client credentials (you don’t need ‘Authorization code flow with PKCE’)
  4. Save the client
  5. Important: Go to the Authentication tab and copy the Client secret - you’ll need it for authentication

After creating the client, assign the required resource permissions:

  1. Go to the Permissions tab of your client
  2. For Admin API access:
    • Select the authserver resource
    • Assign the appropriate permission(s):
      • manage - Full access to all Admin API endpoints
      • admin-read - Read-only access to all Admin API endpoints
      • manage-users - Full access to user, group, and permission endpoints
      • manage-clients - Full access to client endpoints
      • manage-settings - Full access to settings and key endpoints
  3. For Account API access (self-service endpoints):
    • Select the authserver resource
    • Assign the manage-account permission
    • This allows users to manage their own accounts

Once your client is configured with the required permissions, use the client credentials flow to obtain an access token:

Terminal window
curl -X POST https://auth.example.com/auth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=your-client-id" \
-d "client_secret=your-client-secret" \
-d "scope=authserver:manage"

For granular access, request only the scopes you need:

Terminal window
# Read-only access to all admin endpoints
-d "scope=authserver:admin-read"
# Full access to user management only
-d "scope=authserver:manage-users"
# Multiple scopes (space-separated)
-d "scope=authserver:manage-users authserver:manage-clients"

Response:

{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 300
}

Use the access_token in the Authorization header for subsequent API calls.

Goiabada provides a complete OpenAPI 3.0 specification for the REST APIs, which you can use with tools like Swagger UI, Postman, or code generators.

The OpenAPI specification is available at:

GET https://auth.example.com/openapi.yaml

This endpoint is publicly accessible (no authentication required) and returns the complete API specification in YAML format.

You can use the specification with various tools:

  • Swagger UI: Import the URL to get an interactive API explorer
  • Postman: Import the OpenAPI spec to automatically generate a complete API collection
  • Code generation: Use tools like openapi-generator to generate client SDKs in your preferred language
  • API testing: Use the spec for automated API testing and validation

All endpoints return errors in a consistent format:

{
"error": {
"message": "Human-readable error description",
"code": "ERROR_CODE"
}
}

Common error codes:

  • ACCESS_TOKEN_REQUIRED - Missing or invalid bearer token
  • INVALID_REQUEST_BODY - Malformed JSON in request
  • VALIDATION_ERROR - Input validation failed
  • NOT_FOUND - Resource not found
  • INTERNAL_SERVER_ERROR - Server-side error

The Admin API provides administrative control over your Goiabada instance. Endpoints are organized by domain and support granular authorization:

DomainRead ScopeWrite Scope
Users, Groups, Permissionsauthserver:admin-read or authserver:manage-usersauthserver:manage-users
Clientsauthserver:admin-read or authserver:manage-clientsauthserver:manage-clients
Settings, Resources, Keysauthserver:admin-read or authserver:manage-settingsauthserver:manage-settings

The authserver:manage scope grants full access to all domains (backwards compatible).

GET /api/v1/admin/users/search?query=john&page=1&size=10

Query parameters:

ParameterTypeDescription
querystringSearch term (matches email, username, name)
pageintPage number (default: 1)
sizeintResults per page (default: 10)

Response:

{
"users": [
{
"id": 1,
"email": "[email protected]",
"emailVerified": true,
"username": "johndoe",
"givenName": "John",
"familyName": "Doe",
"enabled": true,
"subject": "550e8400-e29b-41d4-a716-446655440000"
}
],
"total": 1,
"page": 1,
"size": 10
}
GET /api/v1/admin/users/{id}

Returns complete user details including groups, permissions, and attributes.

POST /api/v1/admin/users/create

Request body:

{
"email": "[email protected]",
"emailVerified": false,
"givenName": "New",
"familyName": "User",
"setPasswordType": "now",
"password": "SecurePassword123!"
}
FieldTypeRequiredDescription
emailstringYesUser’s email address
emailVerifiedboolNoWhether email is pre-verified
givenNamestringNoFirst name
middleNamestringNoMiddle name
familyNamestringNoLast name
setPasswordTypestringNo"now" to set password immediately, "email" to send setup email
passwordstringConditionalRequired if setPasswordType is "now"
PUT /api/v1/admin/users/{id}/profile

Request body:

{
"username": "johndoe",
"givenName": "John",
"middleName": "",
"familyName": "Doe",
"nickname": "Johnny",
"website": "https://johndoe.com",
"gender": "male",
"dateOfBirth": "1990-01-15",
"zoneInfoCountryName": "United States",
"zoneInfo": "America/New_York",
"locale": "en-US"
}
PUT /api/v1/admin/users/{id}/email
{
"email": "[email protected]",
"emailVerified": true
}
PUT /api/v1/admin/users/{id}/phone
{
"phoneCountryUniqueId": "US",
"phoneNumber": "5551234567",
"phoneNumberVerified": false
}
PUT /api/v1/admin/users/{id}/address
{
"addressLine1": "123 Main St",
"addressLine2": "Apt 4B",
"addressLocality": "New York",
"addressRegion": "NY",
"addressPostalCode": "10001",
"addressCountry": "US"
}
PUT /api/v1/admin/users/{id}/password
{
"newPassword": "NewSecurePassword123!"
}
PUT /api/v1/admin/users/{id}/enabled
{
"enabled": false
}
PUT /api/v1/admin/users/{id}/otp
{
"enabled": false
}
DELETE /api/v1/admin/users/{id}

Custom key-value attributes that can be included in tokens.

GET /api/v1/admin/users/{id}/attributes
GET /api/v1/admin/user-attributes/{id}

Returns a single user attribute by ID.

POST /api/v1/admin/user-attributes
{
"userId": 1,
"key": "department",
"value": "Engineering",
"includeInIdToken": true,
"includeInAccessToken": false
}
PUT /api/v1/admin/user-attributes/{id}
DELETE /api/v1/admin/user-attributes/{id}

GET /api/v1/admin/users/{id}/sessions

Returns enhanced session details including device info, IP address, and validity status.

GET /api/v1/admin/user-sessions/{sessionIdentifier}

Returns details for a specific session by its session identifier.

PUT /api/v1/admin/user-sessions/{sessionIdentifier}

Updates session metadata (implementation specific).

DELETE /api/v1/admin/user-sessions/{id}

Terminates a user session by ID.


GET /api/v1/admin/users/{id}/consents
DELETE /api/v1/admin/user-consents/{id}

GET /api/v1/admin/groups

Returns all groups in the system.

Response:

{
"groups": [
{
"id": 1,
"groupIdentifier": "developers",
"description": "Development team",
"includeInIdToken": true,
"includeInAccessToken": true,
"memberCount": 5
}
]
}
GET /api/v1/admin/groups/search?query=dev

Search for groups by name or description.

Query parameters:

ParameterTypeDescription
querystringSearch term (matches group identifier and description)
POST /api/v1/admin/groups
{
"groupIdentifier": "developers",
"description": "Development team",
"includeInIdToken": true,
"includeInAccessToken": true
}
GET /api/v1/admin/groups/{id}
PUT /api/v1/admin/groups/{id}
DELETE /api/v1/admin/groups/{id}

GET /api/v1/admin/groups/{id}/members?page=1&size=10
POST /api/v1/admin/groups/{id}/members
{
"userId": 1
}
DELETE /api/v1/admin/groups/{id}/members/{userId}

GET /api/v1/admin/users/{id}/groups
PUT /api/v1/admin/users/{id}/groups
{
"groupIds": [1, 2, 3]
}

Custom key-value attributes for groups that can be included in tokens.

GET /api/v1/admin/groups/{id}/attributes
POST /api/v1/admin/group-attributes
{
"groupId": 1,
"key": "costCenter",
"value": "CC-1234",
"includeInIdToken": true,
"includeInAccessToken": false
}
PUT /api/v1/admin/group-attributes/{id}
DELETE /api/v1/admin/group-attributes/{id}

Resources represent APIs or services that can be protected with permissions.

GET /api/v1/admin/resources
POST /api/v1/admin/resources
{
"resourceIdentifier": "product-api",
"description": "Product catalog API"
}
GET /api/v1/admin/resources/{id}
PUT /api/v1/admin/resources/{id}
DELETE /api/v1/admin/resources/{id}
GET /api/v1/admin/resources/{id}/permissions
PUT /api/v1/admin/resources/{id}/permissions
{
"permissions": [
{
"permissionIdentifier": "read",
"description": "Read access"
},
{
"id": 5,
"permissionIdentifier": "write",
"description": "Write access (updated)"
}
]
}

GET /api/v1/admin/users/{id}/permissions
PUT /api/v1/admin/users/{id}/permissions
{
"permissionIds": [1, 2, 3]
}
GET /api/v1/admin/groups/{id}/permissions
PUT /api/v1/admin/groups/{id}/permissions
{
"permissionIds": [1, 2, 3]
}
GET /api/v1/admin/permissions/{id}/users?page=1&size=10

OAuth2/OIDC client applications.

GET /api/v1/admin/clients
POST /api/v1/admin/clients
{
"clientIdentifier": "my-web-app",
"description": "My web application",
"authorizationCodeEnabled": true,
"clientCredentialsEnabled": false
}
GET /api/v1/admin/clients/{id}
PUT /api/v1/admin/clients/{id}
{
"clientIdentifier": "my-web-app",
"description": "Updated description",
"enabled": true,
"consentRequired": true,
"defaultAcrLevel": "urn:goiabada:level1"
}
PUT /api/v1/admin/clients/{id}/authentication
{
"isPublic": false,
"clientSecret": "new-secret-value"
}
PUT /api/v1/admin/clients/{id}/oauth2-flows
{
"authorizationCodeEnabled": true,
"clientCredentialsEnabled": true
}
PUT /api/v1/admin/clients/{id}/redirect-uris
{
"redirectURIs": [
"https://myapp.com/callback",
"https://myapp.com/silent-refresh"
]
}
PUT /api/v1/admin/clients/{id}/web-origins
{
"webOrigins": [
"https://myapp.com"
]
}
PUT /api/v1/admin/clients/{id}/tokens
{
"tokenExpirationInSeconds": 3600,
"refreshTokenOfflineIdleTimeoutInSeconds": 2592000,
"refreshTokenOfflineMaxLifetimeInSeconds": 31536000,
"includeOpenIDConnectClaimsInAccessToken": "default"
}
GET /api/v1/admin/clients/{id}/permissions
PUT /api/v1/admin/clients/{id}/permissions
{
"permissionIds": [1, 2, 3]
}
GET /api/v1/admin/clients/{id}/sessions?page=1&size=10
DELETE /api/v1/admin/clients/{id}

GET /api/v1/admin/settings/general
PUT /api/v1/admin/settings/general
{
"appName": "My Auth Server",
"issuer": "https://auth.example.com",
"selfRegistrationEnabled": true,
"selfRegistrationRequiresEmailVerification": true,
"dynamicClientRegistrationEnabled": false,
"passwordPolicy": "at_least_8_chars_one_number_one_uppercase_one_lowercase"
}
GET /api/v1/admin/settings/email
PUT /api/v1/admin/settings/email
{
"smtpEnabled": true,
"smtpHost": "smtp.example.com",
"smtpPort": 587,
"smtpUsername": "[email protected]",
"smtpPassword": "password",
"smtpEncryption": "starttls",
"smtpFromName": "My App",
"smtpFromEmail": "[email protected]"
}
POST /api/v1/admin/settings/email/send-test
GET /api/v1/admin/settings/sessions
PUT /api/v1/admin/settings/sessions
{
"userSessionIdleTimeoutInSeconds": 7200,
"userSessionMaxLifetimeInSeconds": 86400
}
GET /api/v1/admin/settings/ui-theme
PUT /api/v1/admin/settings/ui-theme
{
"uiTheme": "dark"
}
GET /api/v1/admin/settings/tokens
PUT /api/v1/admin/settings/tokens
{
"tokenExpirationInSeconds": 300,
"refreshTokenOfflineIdleTimeoutInSeconds": 2592000,
"refreshTokenOfflineMaxLifetimeInSeconds": 31536000,
"includeOpenIDConnectClaimsInAccessToken": false
}
GET /api/v1/admin/settings/keys

Returns all signing keys with their public key material in PEM and JWK formats.

POST /api/v1/admin/settings/keys/rotate

Rotates to a new signing key. The old key remains available for validation.

DELETE /api/v1/admin/settings/keys/{id}

GET /api/v1/admin/phone-countries

Returns list of countries with calling codes for phone number validation.


The Account API provides self-service endpoints for authenticated users to manage their own account. All endpoints require the authserver:manage-account scope.

GET /api/v1/account/profile

Returns the authenticated user’s complete profile.

PUT /api/v1/account/profile
{
"username": "johndoe",
"givenName": "John",
"middleName": "",
"familyName": "Doe",
"nickname": "Johnny",
"website": "https://johndoe.com",
"gender": "male",
"dateOfBirth": "1990-01-15",
"zoneInfoCountryName": "United States",
"zoneInfo": "America/New_York",
"locale": "en-US"
}

PUT /api/v1/account/email
{
"email": "[email protected]"
}
POST /api/v1/account/email/verification/send

No request body required. Returns:

{
"emailVerificationSent": true,
"emailDestination": "j***@example.com",
"tooManyRequests": false,
"waitInSeconds": 0,
"emailVerified": false
}
POST /api/v1/account/email/verification
{
"verificationCode": "ABC123"
}

The verification code is 6 characters (3 letters + 3 numbers) and expires after 5 minutes.


PUT /api/v1/account/phone
{
"phoneCountryUniqueId": "US",
"phoneNumber": "5551234567"
}

Send an empty phoneNumber to clear the phone number.


PUT /api/v1/account/address
{
"addressLine1": "123 Main St",
"addressLine2": "Apt 4B",
"addressLocality": "New York",
"addressRegion": "NY",
"addressPostalCode": "10001",
"addressCountry": "US"
}

PUT /api/v1/account/password
{
"currentPassword": "OldPassword123!",
"newPassword": "NewPassword456!"
}

GET /api/v1/account/otp/enrollment

Returns a QR code and secret key for TOTP setup:

{
"base64Image": "data:image/png;base64,...",
"secretKey": "JBSWY3DPEHPK3PXP"
}
PUT /api/v1/account/otp

Enable OTP:

{
"enabled": true,
"password": "CurrentPassword123!",
"otpCode": "123456",
"secretKey": "JBSWY3DPEHPK3PXP"
}

Disable OTP:

{
"enabled": false,
"password": "CurrentPassword123!"
}

GET /api/v1/account/consents

Returns all OAuth2 client consents granted by the user.

DELETE /api/v1/account/consents/{id}

GET /api/v1/account/sessions

Returns all active sessions with device info and validity status. Each session includes an isCurrent flag indicating if it’s the current session.

DELETE /api/v1/account/sessions/{id}

POST /api/v1/account/logout-request
{
"postLogoutRedirectUri": "https://myapp.com/logged-out",
"state": "xyz123",
"clientIdentifier": "my-app",
"responseMode": "redirect"
}
FieldTypeRequiredDescription
postLogoutRedirectUristringYesURI to redirect after logout
statestringNoState parameter (echoed back)
clientIdentifierstringNoClient ID (auto-resolved if omitted)
responseModestringNo"form_post" or "redirect"

Response:

{
"logoutUrl": "https://auth.example.com/auth/logout?id_token_hint=..."
}

Follow the logoutUrl to complete the logout process.