# Service Accounts https://api-docs.lumar.io/docs/graphql/service-accounts Service Accounts provide a way to grant programmatic access to the Lumar API without requiring user credentials. They are ideal for automated pipelines, CI/CD integrations, and server-to-server communication. ## Overview Service accounts are associated with a Lumar account and have a configurable role that determines their access permissions. Each service account can have multiple API keys, which are used for authentication. ### Key Concepts - **Service Account**: An identity for programmatic API access, associated with a specific Lumar account - **Service Account Key**: An API key used to authenticate as a service account. Keys can be named, have expiration dates, and can be revoked - **Role**: Determines what operations the service account can perform (e.g., `Admin`, `Editor`, `Viewer`) ### API Key Format Service account API keys follow this format: ``` lmr_sa_{serviceAccountId}_{secret} ``` The full key is only visible **once** when created. Store it securely as it cannot be retrieved later. ## Authentication To authenticate using a service account, include the API key in the `x-api-key` header: ```bash curl -H "x-api-key: lmr_sa_123_your-secret-key" \ -X POST https://api.lumar.io/graphql \ -H "Content-Type: application/json" \ --data-raw '{"query": "{ node(id: \"TjAwN0FjY291bnQ3MTU\") { ... on Account { id name } } }"}' ``` The service account will have access to resources based on its assigned role within the associated account. ## Prerequisites - You must have **Admin** role access to the Lumar account - Service accounts can only be managed by authenticated users (not other service accounts) ## Creating a Service Account Use the `createServiceAccount` mutation to create a new service account. ```graphql mutation CreateServiceAccount($input: CreateServiceAccountInput!) { createServiceAccount(input: $input) { serviceAccount { id name description roleCode enabled createdAt } } } ``` **Variables:** ```json { "input": { "accountId": "TjAwN0FjY291bnQ3MTU", "name": "CI/CD Pipeline", "description": "Service account for automated deployments", "roleCode": "Editor" } } ``` **Response:** ```json { "data": { "createServiceAccount": { "serviceAccount": { "id": "TjAzNlNlcnZpY2VBY2NvdW50MQ", "name": "CI/CD Pipeline", "description": "Service account for automated deployments", "roleCode": "Editor", "enabled": true, "createdAt": "2024-12-23T10:00:00.000Z" } } } } ``` ### Input Fields | Field | Type | Required | Description | | ------------- | -------- | -------- | ------------------------------------------------------ | | `accountId` | ObjectID | Yes | The ID of the account to create the service account in | | `name` | String | Yes | A name for the service account (max 255 characters) | | `description` | String | No | A description of the service account's purpose | | `roleCode` | RoleCode | Yes | The role to assign (`Admin`, `Editor`, or `Viewer`) | ## Listing Service Accounts Query the `serviceAccounts` field on an Account to list all service accounts. ```graphql query GetServiceAccounts($accountId: ObjectID!) { node(id: $accountId) { ... on Account { id name serviceAccounts { id name description roleCode enabled createdAt updatedAt keys { id name lastUsedAt expiresAt revokedAt createdAt } } } } } ``` **Variables:** ```json { "accountId": "TjAwN0FjY291bnQ3MTU" } ``` **Response:** ```json { "data": { "node": { "id": "TjAwN0FjY291bnQ3MTU", "name": "My Account", "serviceAccounts": [ { "id": "TjAzNlNlcnZpY2VBY2NvdW50MQ", "name": "CI/CD Pipeline", "description": "Service account for automated deployments", "roleCode": "Editor", "enabled": true, "createdAt": "2024-12-23T10:00:00.000Z", "updatedAt": "2024-12-23T10:00:00.000Z", "keys": [ { "id": "TjAzN1NlcnZpY2VBY2NvdW50S2V5MQ", "name": "Production Key", "lastUsedAt": "2024-12-23T15:30:00.000Z", "expiresAt": "2025-12-31T23:59:59.000Z", "revokedAt": null, "createdAt": "2024-12-23T10:00:00.000Z" } ] } ] } } } ``` ## Retrieving a Service Account Use the `serviceAccount` query to get a specific service account by ID. ```graphql query GetServiceAccount($serviceAccountId: ObjectID!) { serviceAccount(id: $serviceAccountId) { id name description roleCode enabled createdAt updatedAt account { id name } createdByUser { id username } role { code name } keys { id name lastUsedAt expiresAt revokedAt createdAt } } } ``` **Variables:** ```json { "serviceAccountId": "TjAzNlNlcnZpY2VBY2NvdW50MQ" } ``` **Response:** ```json { "data": { "serviceAccount": { "id": "TjAzNlNlcnZpY2VBY2NvdW50MQ", "name": "CI/CD Pipeline", "description": "Service account for automated deployments", "roleCode": "Editor", "enabled": true, "createdAt": "2024-12-23T10:00:00.000Z", "updatedAt": "2024-12-23T10:00:00.000Z", "account": { "id": "TjAwN0FjY291bnQ3MTU", "name": "My Account" }, "createdByUser": { "id": "TjAwOFVzZXIxMjM", "username": "admin@example.com" }, "role": { "code": "Editor", "name": "Editor" }, "keys": [ { "id": "TjAzN1NlcnZpY2VBY2NvdW50S2V5MQ", "name": "Production Key", "lastUsedAt": "2024-12-23T15:30:00.000Z", "expiresAt": "2025-12-31T23:59:59.000Z", "revokedAt": null, "createdAt": "2024-12-23T10:00:00.000Z" } ] } } } ``` ## Updating a Service Account Use the `updateServiceAccount` mutation to modify a service account's properties. ```graphql mutation UpdateServiceAccount($input: UpdateServiceAccountInput!) { updateServiceAccount(input: $input) { serviceAccount { id name description roleCode enabled updatedAt } } } ``` **Variables:** ```json { "input": { "id": "TjAzNlNlcnZpY2VBY2NvdW50MQ", "name": "Production CI/CD Pipeline", "enabled": true } } ``` **Response:** ```json { "data": { "updateServiceAccount": { "serviceAccount": { "id": "TjAzNlNlcnZpY2VBY2NvdW50MQ", "name": "Production CI/CD Pipeline", "description": "Service account for automated deployments", "roleCode": "Editor", "enabled": true, "updatedAt": "2024-12-23T11:00:00.000Z" } } } } ``` ### Updatable Fields | Field | Type | Description | | ------------- | -------- | ------------------------------------- | | `name` | String | Update the service account name | | `description` | String | Update or clear the description | | `roleCode` | RoleCode | Change the assigned role | | `enabled` | Boolean | Enable or disable the service account | ## Deleting a Service Account Use the `deleteServiceAccount` mutation to remove a service account. This will also invalidate all associated API keys. ```graphql mutation DeleteServiceAccount($input: DeleteServiceAccountInput!) { deleteServiceAccount(input: $input) { serviceAccount { id } } } ``` **Variables:** ```json { "input": { "id": "TjAzNlNlcnZpY2VBY2NvdW50MQ" } } ``` **Response:** ```json { "data": { "deleteServiceAccount": { "serviceAccount": { "id": "TjAzNlNlcnZpY2VBY2NvdW50MQ" } } } } ``` ## Managing API Keys ### Creating an API Key Use the `createServiceAccountKey` mutation to generate a new API key. **Important**: The `secret` field must be requested and will only be returned once. ```graphql mutation CreateServiceAccountKey($input: CreateServiceAccountKeyInput!) { createServiceAccountKey(input: $input) { id name secret expiresAt createdAt } } ``` **Variables:** ```json { "input": { "serviceAccountId": "TjAzNlNlcnZpY2VBY2NvdW50MQ", "name": "Production Key", "expiresAt": "2025-12-31T23:59:59.000Z" } } ``` **Response:** ```json { "data": { "createServiceAccountKey": { "id": "TjAzN1NlcnZpY2VBY2NvdW50S2V5MQ", "name": "Production Key", "secret": "lmr_sa_1_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0", "expiresAt": "2025-12-31T23:59:59.000Z", "createdAt": "2024-12-23T10:00:00.000Z" } } } ``` ### Input Fields | Field | Type | Required | Description | | ------------------ | -------- | -------- | ------------------------------------ | | `serviceAccountId` | ObjectID | Yes | The ID of the service account | | `name` | String | No | A name to identify this key | | `expiresAt` | DateTime | No | Optional expiration date for the key | ### Listing API Keys API keys are accessible via the `keys` field on a ServiceAccount: ```graphql query GetServiceAccountKeys($serviceAccountId: ObjectID!) { serviceAccount(id: $serviceAccountId) { id name keys { id name lastUsedAt expiresAt revokedAt createdAt createdByUser { id username } } } } ``` **Variables:** ```json { "serviceAccountId": "TjAzNlNlcnZpY2VBY2NvdW50MQ" } ``` **Response:** ```json { "data": { "serviceAccount": { "id": "TjAzNlNlcnZpY2VBY2NvdW50MQ", "name": "CI/CD Pipeline", "keys": [ { "id": "TjAzN1NlcnZpY2VBY2NvdW50S2V5MQ", "name": "Production Key", "lastUsedAt": "2024-12-23T15:30:00.000Z", "expiresAt": "2025-12-31T23:59:59.000Z", "revokedAt": null, "createdAt": "2024-12-23T10:00:00.000Z", "createdByUser": { "id": "TjAwOFVzZXIxMjM", "username": "admin@example.com" } }, { "id": "TjAzN1NlcnZpY2VBY2NvdW50S2V5Mg", "name": "Staging Key", "lastUsedAt": null, "expiresAt": null, "revokedAt": "2024-12-20T10:00:00.000Z", "createdAt": "2024-12-01T10:00:00.000Z", "createdByUser": { "id": "TjAwOFVzZXIxMjM", "username": "admin@example.com" } } ] } } } ``` Note: The `secret` field is only returned when creating a key. For existing keys, only metadata (name, creation date, last used, expiration, revocation status) is available. ### Revoking an API Key Use the `revokeServiceAccountKey` mutation to revoke an API key. Revoked keys cannot be used for authentication. ```graphql mutation RevokeServiceAccountKey($input: RevokeServiceAccountKeyInput!) { revokeServiceAccountKey(input: $input) { serviceAccountKey { id revokedAt } } } ``` **Variables:** ```json { "input": { "id": "TjAzN1NlcnZpY2VBY2NvdW50S2V5MQ" } } ``` **Response:** ```json { "data": { "revokeServiceAccountKey": { "serviceAccountKey": { "id": "TjAzN1NlcnZpY2VBY2NvdW50S2V5MQ", "revokedAt": "2024-12-23T12:00:00.000Z" } } } } ``` ## Best Practices 1. **Use descriptive names**: Give service accounts and keys meaningful names that indicate their purpose 2. **Set expiration dates**: Use expiring keys for temporary access or rotate keys regularly 3. **Use minimal permissions**: Assign the lowest role that meets your needs 4. **Secure storage**: Store API keys securely (e.g., in environment variables or secret managers) 5. **Monitor usage**: Check the `lastUsedAt` field to track key usage 6. **Revoke unused keys**: Remove keys that are no longer needed 7. **One key per integration**: Create separate keys for different integrations to simplify revocation ## Access Control Service accounts inherit permissions based on their assigned role: | Role | Description | | -------- | ----------------------------------------- | | `Admin` | Full access to all account resources | | `Editor` | Can create and modify projects and crawls | | `Viewer` | Read-only access to account resources | Service accounts cannot: - Create or manage other service accounts - Create or manage service account keys - Perform user-specific operations (e.g., managing user settings) ## Error Handling Common errors when working with service accounts: | Error | Description | | ----------------------------------------- | ------------------------------------------------------------------------ | | `Unauthorized` | You don't have Admin access to the account | | `ServiceAccount not found` | The specified service account doesn't exist or you don't have access | | `The 'secret' field must be requested...` | When creating a key, you must request the `secret` field in the response |