Manage apps
Atlan apps are connector workflows—crawlers, miners, and enrichment jobs—that
you create and run on your tenant. The AppClient (client.app) is the single
entry point for the full app lifecycle: create, run, inspect, update, schedule,
and delete.
There are two ways to build the inputs for an app:
- Typed builders (recommended)—a fluent, UI-equivalent builder per connector (see Supported apps). The builder vaults credentials, mints the connection, and assembles the full payload for you, so you never hand-build a connection object or guess an input key.
- A raw
inputsdict—for any app, including ones without a builder. Pass the values dict directly toclient.app.create(...); the server validates it with the app's input contract.
Creating an app with run=True (or calling .run() on a builder) submits a run
that executes in the background. Use get_run to poll the
run's status until it's terminal.
Create an app
A builder's .create() builds and publishes the workflow without running it;
.run() does the same and immediately submits a run. Both return an
AppResponse—persist its slug, which identifies the workflow for every
later operation.
- Python
from pyatlan.client.atlan import AtlanClient
from pyatlan.model.apps import BigqueryCrawler
client = AtlanClient()
response = (
BigqueryCrawler(client) # (1)
.service_account( # (2)
email="svc@my-project.iam.gserviceaccount.com",
service_account_json=sa_json,
project_id="my-project",
)
.connection( # (3)
name="production-bigquery",
admin_roles=[client.role_cache.get_id_for_name("$admin")],
)
.include({"my-project": ["analytics", "sales"]}) # (4)
.run(name="bigquery-prod") # (5)
)
print(response.slug, response.run_id) # (6)
- Each connector has its own builder—see Supported apps.
- Step 1—Credential. Pick the auth method your source uses; the builder vaults the secret and never persists it in the workflow.
- Step 2—Connection. Provide a display name and at least one admin (user, group, or role). The builder mints the connection qualified name.
- Step 3—Metadata. Configure what to crawl and how.
.run(name=...)creates and submits a run. Use.create(name=...)to create the workflow without running it.- Persist
response.slug—you need it to inspect, update, schedule, re-run, or delete the workflow.
To build an app without a builder, pass a raw inputs dict:
- Python
response = client.app.create(
app_id="bigquery-crawler", # (1)
entrypoint="crawler", # (2)
name="bigquery-prod",
inputs={...}, # (3)
run=True, # (4)
)
- The marketplace application id.
- Optional—omit to use the app's default entrypoint.
- The values dict matching the app's input contract. See Inspect an app's input contract to discover the available keys.
- Submit a run on create. The server defaults to
Truewhen omitted.
Re-run an existing app
Calling a builder's .run()/.create() again creates a new connection and
new assets, which can produce duplicates. To re-crawl, submit a new run of the
existing workflow with its slug.
- Python
run = client.app.submit("bigquery-prod-AbC123") # (1)
print(run.run_id, run.status)
- The
slugreturned when the workflow was first created.
List apps
- Python
page = client.app.get_all(limit=50) # (1)
for app in page.workflows: # (2)
print(app.slug, app.name)
# page.has_more / page.next_cursor -> pass cursor= back to paginate
limitis the page size (server default 50).- Iterate
page.workflows; ifpage.has_more, passpage.next_cursorascursor=on the next call.
Get a single app
- Python
summary = client.app.get("bigquery-prod-AbC123") # (1)
print(summary.app_id, summary.name, summary.version)
- The workflow
slug.
Get a run's status
Runs are asynchronous—poll until the run is terminal.
- Python
import time
while True:
run = client.app.get_run("a1b2c3d4-...") # (1)
print(run.status)
if run.is_terminal: # (2)
print("done:", run.status, "success:", run.is_success)
break
time.sleep(10)
- The
run_idfromcreate(run=True)/run()/submit(). is_terminalisTrueonce the run has finished (succeeded, failed, or cancelled);is_successreports the outcome.
Cancel a run
- Python
client.app.cancel_run("a1b2c3d4-...") # (1)
- The
run_idof the run to cancel.
Update an app
Replace a workflow's inputs and publish a new version on the same slug. This is a
full replace—send the complete inputs. Omit the credential to keep the
persisted one.
- Python
updated = client.app.update(
slug="bigquery-prod-AbC123", # (1)
inputs={...}, # (2)
)
print(updated.version) # (3)
- The workflow
slug. - The complete input-contract values (a dict, or an
AppInputfrom a builder'spreview()). - A new
versionis published on the same slug.
Schedule an app
Attach a cron schedule to the latest published version.
- Python
added = client.app.add_schedule(
slug="bigquery-prod-AbC123", # (1)
cron="0 9 * * *", # (2)
timezone="Asia/Kolkata", # (3)
)
client.app.remove_schedule(
slug="bigquery-prod-AbC123",
trigger_id=added.trigger_id, # (4)
)
- The workflow
slug. - A standard cron expression (here: every day at 09:00).
- Optional IANA timezone; defaults to
UTCwhen omitted. - Removing a schedule needs the
trigger_idreturned when it was added.
You can also attach a schedule when creating the app, by passing schedule= to
.create() / .run() (builders) or client.app.create(...).
Delete an app
- Python
result = client.app.delete("bigquery-prod-AbC123") # (1)
print(result.archived)
- The workflow
slug.
Inspect an app's input contract
Every app validates its inputs with a server-side input contract. Fetch it
to discover the available keys, types, and defaults—useful when building a raw
inputs dict, or to check whether an app is runnable on your tenant.
- Python
contract = client.app.get_input_contract("bigquery-crawler") # (1)
print(contract.properties.keys())
- Returns the JSON-schema-style contract. A
404means the app doesn't expose a native input contract on this tenant (it isn't runnable viaclient.appthere yet).
Describe an app
- Python
info = client.app.describe("bigquery-crawler") # (1)
print(info.name, info.native_ready, info.entrypoints)
- Returns the app's metadata (display name, whether it's native-ready, and its entrypoints).
Raw REST API
If you aren't using the SDK, call the app endpoints directly. They're served under
the gateway prefix api/service/ on your tenant, and authenticated with an API key
via the Authorization: Bearer <api-key> header.
| Operation | Method & path |
|---|---|
| Create (+ version, publish, optional run) | POST /api/service/v1/app |
| List published workflows | GET /api/service/v1/app |
| Get one workflow | GET /api/service/v1/app/{slug} |
| Update (full-replace inputs, new version) | PUT /api/service/v1/app/{slug} |
| Delete (archive) | DELETE /api/service/v1/app/{slug} |
| Submit a run | POST /api/service/v1/app/{slug}/submit |
| Get a run's status | GET /api/service/v1/app/runs/{run_id} |
| Cancel a run | POST /api/service/v1/app/runs/{run_id}/cancel |
| Add a schedule | POST /api/service/v1/app/{slug}/schedule |
| Remove a schedule | DELETE /api/service/v1/app/{slug}/schedule/{trigger_id} |
| Describe an app | GET /api/service/v1/apps/{app_id} |
| Get an app's input contract | GET /api/service/v1/apps/{app_id}/inputs |
- Raw REST API
curl -X POST "https://<tenant>.atlan.com/api/service/v1/app" \
-H "Authorization: Bearer $ATLAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"app_id": "bigquery-crawler",
"entrypoint": "crawler",
"name": "bigquery-prod",
"run": true,
"inputs": {
"connection": {
"typeName": "Connection",
"attributes": {
"qualifiedName": "default/bigquery/1700000000",
"connectorName": "bigquery",
"name": "production-bigquery",
"adminRoles": ["<role-guid>"]
}
},
"extraction_method": "direct",
"credential": {
"authType": "basic",
"connectorConfigName": "atlan-connectors-bigquery",
"username": "svc@my-project.iam.gserviceaccount.com",
"password": "<service-account-json>",
"host": "https://bigquery.googleapis.com",
"port": 443,
"extra": {"project_id": "my-project", "connect_type": "public"}
},
"credential_guid": "",
"include_filter": "{\"^my-project$\": [\"^analytics$\"]}"
}
}'
The response contains the slug and (when run: true) the run_id. A raw
credential placed in the credential key is vaulted server-side and the issued
guid is routed into credential_guid.
- Raw REST API
curl "https://<tenant>.atlan.com/api/service/v1/app/runs/<run_id>" \
-H "Authorization: Bearer $ATLAN_API_KEY"
# -> {"run_id": "...", "slug": "...", "status": "Running"}
inputs is validated against the app's input contract. Fetch it with
GET /api/service/v1/apps/{app_id}/inputs to see the available keys, types, and
defaults before hand-building a payload.