# Tutorial: Setup Automated Monitoring https://api-docs.lumar.io/docs/graphql/tutorials/setup-automated-monitoring This tutorial walks through setting up automated monitoring for your site using projects, tests, build schedules, and webhook notifications. :::note In Lumar's GraphQL schema, `Project` and `TestSuite` both implement the `BaseProject` interface and are effectively the same entity. This tutorial uses project-centric language. Some mutations still use `testSuiteId` as a parameter name -- pass your **project ID** to these fields. ::: ## Overview Lumar's monitoring workflow consists of: 1. **Projects** -- containers that group tests, builds, and monitoring configuration. 2. **Tests** -- individual assertions (e.g., "Broken pages must be below 10"). 3. **Build Schedules** -- cron-based schedules that automatically trigger builds. 4. **Webhooks** -- notifications sent when builds complete. ## Step 1: Find or create a project Query existing monitor projects for your account: ```graphql query GetMonitorProjects($accountId: ObjectID!) { getAccount(id: $accountId) { monitorProjects(first: 10) { nodes { id name lastFinishedCrawl { id status createdAt } } totalCount } } } ``` **Variables:** ```json { "accountId": "TjAwN0FjY291bnQ3MTU" } ``` **Response:** ```json { "data": { "getAccount": { "monitorProjects": { "nodes": [ { "id": "TjAxMVRlc3RTdWl0ZTEyMw", "name": "Production SEO Suite", "lastFinishedCrawl": { "id": "TjAwNUNyYXdsMTc2NjI0MQ", "status": "Finished", "createdAt": "2025-01-15T10:00:00.000Z" } } ], "totalCount": 1 } } } } ``` If you need to create a project, see the [Protect documentation](/docs/protect/test-suites/create-test-suites.md) for the `createTestSuite` mutation. ## Step 2: Add tests Tests define the thresholds for your monitoring. You can add both report-level tests and health score tests. For health score tests: ```graphql mutation CreateHealthScoreTest($input: CreateHealthScoreTestInput!) { createHealthScoreTest(input: $input) { healthScoreTest { absoluteThreshold automaticThresholdEnabled reportCategoryCode severity thresholdPredicate thresholdType } } } ``` **Variables:** ```json { "input": { "testSuiteId": "TjAxMVRlc3RTdWl0ZTEyMw", "reportCategoryCode": "seo", "absoluteThreshold": 0.8, "thresholdType": "Relative", "relativeThreshold": 10, "severity": "Fail", "automaticThresholdEnabled": false } } ``` **Response:** ```json { "data": { "createHealthScoreTest": { "healthScoreTest": { "absoluteThreshold": 0.8, "automaticThresholdEnabled": false, "reportCategoryCode": "seo", "severity": "Fail", "thresholdPredicate": "GreaterThanOrEqual", "thresholdType": "Relative" } } } } ``` For report-level tests, see the [Tests documentation](/docs/protect/tests/create-tests.md). ## Step 3: Check build schedules Review existing build schedules: ```graphql query GetBuildSchedules($accountId: ObjectID!) { getAccount(id: $accountId) { buildSchedules(first: 5) { nodes { id repetitionRate nextRunAt buildScheduleTestSuites(first: 5) { nodes { testSuite { id name } } } } totalCount } } } ``` **Variables:** ```json { "accountId": "TjAwN0FjY291bnQ3MTU" } ``` **Response:** ```json { "data": { "getAccount": { "buildSchedules": { "nodes": [ { "id": "TjAzN0J1aWxkU2NoZWR1bGUx", "repetitionRate": "Weekly", "nextRunAt": "2025-01-20T00:00:00.000Z", "buildScheduleTestSuites": { "nodes": [ { "testSuite": { "id": "TjAxMVRlc3RTdWl0ZTEyMw", "name": "Production SEO Suite" } } ] } } ], "totalCount": 1 } } } } ``` Build schedules use cron expressions. Common examples: | Schedule | Cron Expression | | ------------------------ | --------------- | | Every Monday at midnight | `0 0 * * 1` | | Daily at 6am | `0 6 * * *` | | Every 6 hours | `0 */6 * * *` | | First of every month | `0 0 1 * *` | To create or manage build schedules, see the [Build Schedules documentation](/docs/protect/build-schedules/create-build-schedules.md). ## Step 4: Trigger a build manually (optional) You can trigger a build immediately without waiting for the schedule: ```graphql mutation CreateAndRunBuild($input: CreateAndRunBuildInput!) { createAndRunBuild(input: $input) { build { id status createdAt } } } ``` **Variables:** ```json { "input": { "testSuiteId": "TjAxMVRlc3RTdWl0ZTEyMw" } } ``` **Response:** ```json { "data": { "createAndRunBuild": { "build": { "id": "TjAxMkJ1aWxkNDU3", "status": "Queued", "createdAt": "2025-01-15T10:00:00.000Z" } } } } ``` ## Step 5: Set up webhooks Configure Slack notifications so your team is alerted when builds complete: ```graphql mutation CreateSlackWebhook($input: CreateSlackWebhookInput!) { createAutomatorSlackWebhook(input: $input) { slackWebhook { id url alertTypes createdAt } } } ``` **Variables:** ```json { "input": { "testSuiteId": "TjAxMVRlc3RTdWl0ZTEyMw", "url": "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX", "alertTypes": ["Pass", "Warning", "Fail"] } } ``` **Response:** ```json { "data": { "createAutomatorSlackWebhook": { "slackWebhook": { "id": "TjAzN1NsYWNrV2ViaG9vazE", "url": "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX", "alertTypes": ["Pass", "Warning", "Fail"], "createdAt": "2025-01-15T10:00:00.000Z" } } } } ``` Or set up an API callback webhook: ```graphql mutation CreateWebhook($input: CreateWebhookInput!) { createWebhook(input: $input) { webhook { id url alertTypes webhookTemplateType createdAt } } } ``` **Variables:** ```json { "input": { "testSuiteId": "TjAxMVRlc3RTdWl0ZTEyMw", "url": "https://example.com/api/lumar-webhook", "alertTypes": ["Pass", "Warning", "Fail"], "webhookTemplateType": "MSTeams" } } ``` **Response:** ```json { "data": { "createWebhook": { "webhook": { "id": "TjAzN1dlYmhvb2sx", "url": "https://example.com/api/lumar-webhook", "alertTypes": ["Pass", "Warning", "Fail"], "webhookTemplateType": "MSTeams", "createdAt": "2025-01-15T10:00:00.000Z" } } } } ``` ## Step 6: Review results After a build completes, query the project's test results: ```graphql query GetTestResults($testSuiteId: ObjectID!) { node(id: $testSuiteId) { ... on TestSuite { id name builds(first: 1, orderBy: [{ field: createdAt, direction: DESC }]) { nodes { id status createdAt testResults(first: 10) { nodes { id passed reportTemplate { code name } absoluteThreshold reportTotalRows severity } totalCount } } } } } } ``` **Variables:** ```json { "testSuiteId": "TjAxMVRlc3RTdWl0ZTEyMw" } ``` **Response:** ```json { "data": { "node": { "id": "TjAxMVRlc3RTdWl0ZTEyMw", "name": "Production SEO Suite", "builds": { "nodes": [ { "id": "TjAxMkJ1aWxkNDU2", "status": "Finished", "createdAt": "2025-01-15T10:00:00.000Z", "testResults": { "nodes": [ { "id": "TjAxM1Rlc3RSZXN1bHQ3ODk", "passed": true, "reportTemplate": { "code": "broken_pages", "name": "Broken Pages" }, "absoluteThreshold": 5.0, "reportTotalRows": 2.0, "severity": "Fail" } ], "totalCount": 1 } } ] } } } } ``` ## Next steps - [Webhooks guide](../webhooks.md) -- full webhook configuration reference. - [Health Scores guide](../health-scores.md) -- deep dive into health score tests and thresholds. - [Monitor guide](../monitor.md) -- managing notifications and monitoring workflows.