> ## Documentation Index
> Fetch the complete documentation index at: https://docs.domino.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Getting started with Domino: Build a transaction review App

> Build and deploy a versioned transaction review App with a Git-based Project, Domino Dataset, and authenticated model endpoint.

Use an external Git repository connected to a Domino Git-based Project. Follow [Create a Git-based Project](/cloud/platform-capabilities/core-concepts/projects/create-projects), and add Git credentials only for a private repository or Workspace pushes.

Build a simple Dash App and logistic regression model for reviewing 300 synthetic transactions. Do not use either in production.

Follow [Create a Domino Environment](/cloud/platform-capabilities/core-concepts/compute-environments/manage-compute-environments/3-create-an-environment) and [Customize your Environment](/cloud/platform-capabilities/core-concepts/compute-environments/manage-compute-environments/5-edit-environment-definition) during the Environment exercise.

## Project files

1. `generate_data.py` generates 300 transactions with synthetic routes and writes them to a Dataset.
2. `model.py` trains the model, logs the run with MLflow, saves the model, and defines the endpoint function.
3. `app.py` creates the transaction review interface, calls the endpoint, and records session decisions.
4. `app.sh` starts the App for preview and deployment.

Domino connects these four small files to durable data, reproducible compute, experiment history, an authenticated model service, and a shareable App.

## How the solution fits together

<Frame>
  ```mermaid placement="top-right" theme={null}
  flowchart LR
      git["Git repository"] --> workspace["Workspace"]
      workspace --> dataset["Domino Dataset"]
      workspace --> endpoint["Model endpoint"]
      dataset --> app["Dash App"]
      endpoint --> app
      app --> reviewer["Reviewer"]
  ```
</Frame>

## Configure the Compute Environment

Your Domino deployment must allow Datasets to mount in Apps.

A Compute Environment gives every compute stage the same software stack. The separate Hardware Tier controls its compute resources.

Create the tutorial Compute Environment:

1. Open **Govern** > **Environments** and select **Create Environment**.
2. Name the Environment **Synthetic Transaction Review** and use the Domino Standard Environment as its base.
3. Select **Customize before Building**.
4. Add these Dockerfile instructions:

<Accordion title="View the Compute Environment Dockerfile instructions">
  ```dockerfile theme={null}
  RUN pip install --no-cache-dir dash dash-mantine-components
  ```
</Accordion>

5. Create the Environment and wait for its first revision to change to **Succeeded**.
6. Use this revision and a small CPU Hardware Tier for the Workspace, endpoint, and App.

## Build the transaction review App

<Steps titleSize="h2">
  <Step title="Generate data in a Domino Dataset" id="generate-data">
    In the Git-based Project, create a writable Dataset named `AML`. Start a Workspace from your Git branch with the tutorial Environment revision and CPU Hardware Tier.

    The Dataset outlives the Workspace, so Jobs and Apps can use the same records.

    Add `generate_data.py` to the repository.

    <Accordion title="View generate_data.py, generate the synthetic Dataset">
      ```python generate_data.py theme={null}
      """Create a small synthetic transaction Dataset for the tutorial."""

      from __future__ import annotations

      import os
      from pathlib import Path

      import numpy as np
      import pandas as pd

      DATASET_DIR = Path(
          os.environ.get("TRANSACTION_REVIEW_DATASET", "/mnt/data/AML")
      )
      OUTPUT_PATH = DATASET_DIR / "transactions.csv"
      LOCATIONS = [
          ("Chicago", "United States"),
          ("London", "United Kingdom"),
          ("Mexico City", "Mexico"),
          ("Mumbai", "India"),
          ("Singapore", "Singapore"),
          ("Sydney", "Australia"),
          ("Toronto", "Canada"),
          ("Zurich", "Switzerland"),
      ]
      STREETS = ["Market Street", "Oak Avenue", "Park Road", "River Lane"]


      def synthetic_location(rng) -> tuple[str, str]:
          city, country = LOCATIONS[rng.integers(len(LOCATIONS))]
          address = f"{rng.integers(10, 1_000)} {rng.choice(STREETS)}, {city}"
          return address, country


      def main() -> None:
          if not DATASET_DIR.is_dir():
              raise FileNotFoundError(
                  f"Create and mount the AML Dataset at {DATASET_DIR}"
              )

          rng = np.random.default_rng(6480)
          record_count = 300
          amount = np.round(np.exp(rng.uniform(np.log(50), np.log(50_000), record_count)), 2)
          age_days = rng.integers(5, 1_500, record_count)
          recent_count = rng.integers(0, 11, record_count)
          recent_amount = np.round(amount * rng.uniform(0.5, 4.0, record_count), 2)
          channel = rng.choice(["batch", "online", "treasury"], record_count)

          probability = 1 / (
              1
              + np.exp(
                  -(
                      -4.0
                      + 0.00005 * amount
                      + 0.18 * recent_count
                      + 0.00001 * recent_amount
                      + 0.7 * (age_days < 45)
                  )
              )
          )
          needs_review = rng.binomial(1, probability)
          transaction_date = pd.Timestamp("2026-05-01") + pd.to_timedelta(
              rng.integers(0, 90, record_count), unit="D"
          )
          origins = [synthetic_location(rng) for _ in range(record_count)]
          destinations = [synthetic_location(rng) for _ in range(record_count)]

          transactions = pd.DataFrame(
              {
                  "transaction_id": [f"TX-{index:04d}" for index in range(1, record_count + 1)],
                  "transaction_date": transaction_date.strftime("%Y-%m-%d"),
                  "amount": amount,
                  "counterparty_age_days": age_days,
                  "recent_transaction_count": recent_count,
                  "recent_aggregate_amount": recent_amount,
                  "channel": channel,
                  "origin_address": [address for address, _ in origins],
                  "origin_country": [country for _, country in origins],
                  "destination_address": [address for address, _ in destinations],
                  "destination_country": [country for _, country in destinations],
                  "needs_review": needs_review,
              }
          )
          transactions.to_csv(OUTPUT_PATH, index=False)
          print(f"Wrote {len(transactions)} synthetic transactions to {OUTPUT_PATH}")


      if __name__ == "__main__":
          main()
      ```
    </Accordion>

    Commit and push the file, then run:

    ```bash theme={null}
    python generate_data.py
    ```

    The script writes 300 fixed-seed records to `/mnt/data/AML/transactions.csv`. Open the Dataset and confirm that the file exists.

    <Frame>
      <img src="https://mintcdn.com/dominodatalab-e871cec4/tAN89q5OuNV-ii4x/images/getting-started/synthetic-transaction-review-generate-data.png?fit=max&auto=format&n=tAN89q5OuNV-ii4x&q=85&s=997f1cb5587957e8bc5084ca3792eb05" alt="Domino Workspace showing the transaction review files, mounted AML Dataset, and terminal confirmation that 300 synthetic transactions were generated." width="3072" height="1930" data-path="images/getting-started/synthetic-transaction-review-generate-data.png" />
    </Frame>
  </Step>

  <Step title="Train and deploy the model" id="train-and-deploy-model">
    Add `model.py` to the repository, then commit and push it.

    <Accordion title="View model.py, train and serve the model">
      ```python model.py theme={null}
      """Train and serve the tutorial transaction review model."""

      from __future__ import annotations

      import os
      import pickle
      from functools import lru_cache
      from pathlib import Path

      import mlflow
      import mlflow.sklearn
      import pandas as pd
      from sklearn.compose import ColumnTransformer
      from sklearn.linear_model import LogisticRegression
      from sklearn.metrics import roc_auc_score
      from sklearn.model_selection import train_test_split
      from sklearn.pipeline import make_pipeline
      from sklearn.preprocessing import OneHotEncoder, StandardScaler

      DATASET_DIR = Path(
          os.environ.get("TRANSACTION_REVIEW_DATASET", "/mnt/data/AML")
      )
      DATA_PATH = DATASET_DIR / "transactions.csv"
      MODEL_PATH = Path(__file__).with_name("transaction-review-model.pkl")
      TRAINED_MODEL_PATH = (
          Path(os.environ.get("DOMINO_ARTIFACTS_DIR", MODEL_PATH.parent)) / MODEL_PATH.name
      )
      NUMERIC_FEATURES = [
          "amount",
          "counterparty_age_days",
          "recent_transaction_count",
          "recent_aggregate_amount",
      ]
      FEATURES = [*NUMERIC_FEATURES, "channel"]


      @lru_cache(maxsize=1)
      def load_model():
          """Load the fitted model once per endpoint process."""
          with MODEL_PATH.open("rb") as stream:
              return pickle.load(stream)


      def train() -> None:
          transactions = pd.read_csv(DATA_PATH)
          train_data, evaluation_data = train_test_split(
              transactions,
              test_size=0.25,
              random_state=6480,
              stratify=transactions["needs_review"],
          )
          preprocessing = ColumnTransformer(
              [
                  ("numbers", StandardScaler(), NUMERIC_FEATURES),
                  ("channel", OneHotEncoder(handle_unknown="ignore"), ["channel"]),
              ]
          )
          model = make_pipeline(
              preprocessing,
              LogisticRegression(max_iter=1_000, random_state=6480),
          )
          model.fit(train_data[FEATURES], train_data["needs_review"])
          scores = model.predict_proba(evaluation_data[FEATURES])[:, 1]
          roc_auc = float(roc_auc_score(evaluation_data["needs_review"], scores))

          TRAINED_MODEL_PATH.parent.mkdir(parents=True, exist_ok=True)
          with TRAINED_MODEL_PATH.open("wb") as stream:
              pickle.dump(model, stream)
          print(f"Saved {TRAINED_MODEL_PATH} with evaluation ROC AUC {roc_auc:.3f}")

          project_id = os.environ.get("DOMINO_PROJECT_ID", "local")
          try:
              mlflow.set_experiment(f"synthetic-transaction-review-{project_id}")
              with mlflow.start_run(run_name="train-transaction-review-model"):
                  mlflow.log_param("seed", 6480)
                  mlflow.log_param("training_records", len(train_data))
                  mlflow.log_metric("roc_auc", roc_auc)
                  mlflow.sklearn.log_model(
                      model,
                      name="model",
                      input_example=train_data[FEATURES].head(3),
                  )
          except mlflow.exceptions.MlflowException as error:
              print(f"MLflow logging skipped: {error}")


      def score_transaction(
          transaction_id: str,
          amount: float,
          counterparty_age_days: int,
          recent_transaction_count: int,
          recent_aggregate_amount: float,
          channel: str,
      ) -> dict:
          model = load_model()
          record = pd.DataFrame(
              [
                  {
                      "amount": amount,
                      "counterparty_age_days": counterparty_age_days,
                      "recent_transaction_count": recent_transaction_count,
                      "recent_aggregate_amount": recent_aggregate_amount,
                      "channel": channel,
                  }
              ]
          )
          risk_score = float(model.predict_proba(record[FEATURES])[0, 1])
          priority = "high" if risk_score >= 0.65 else "medium" if risk_score >= 0.35 else "low"
          indicators = []
          if amount >= 25_000:
              indicators.append("amount is at least 25,000")
          if counterparty_age_days < 45:
              indicators.append("counterparty age is less than 45 days")
          if recent_transaction_count >= 8:
              indicators.append("recent transaction count is at least 8")
          if not indicators:
              indicators.append("no tutorial indicators crossed their review levels")
          return {
              "transaction_id": transaction_id,
              "risk_score": round(risk_score, 4),
              "review_priority": priority,
              "review_indicators": indicators,
          }


      if __name__ == "__main__":
          train()
      ```
    </Accordion>

    The Job makes training repeatable outside the Workspace. Domino retains its logs and Artifacts, and MLflow records the run.

    Start a Job with the tutorial Environment revision and CPU Hardware Tier. Use this command:

    ```bash theme={null}
    python model.py
    ```

    The Job trains one logistic regression model and writes `transaction-review-model.pkl` to its Artifacts.

    Download `transaction-review-model.pkl` from the Job's Artifacts, place it beside `model.py`, then commit and push it. In **Deployments** > **Endpoints**, create a synchronous endpoint. The latest default-branch commit packages the trained artifact with its scoring code.

    * File: `model.py`
    * Function: `score_transaction`
    * Environment: the revision used by the Workspace
    * Hardware Tier: a small CPU tier
    * Instances: 1
    * Access: require an access token

    Test the endpoint with one synthetic record:

    ```json theme={null}
    {
      "data": {
        "transaction_id": "TX-TEST-0001",
        "amount": 1250.25,
        "counterparty_age_days": 30,
        "recent_transaction_count": 4,
        "recent_aggregate_amount": 5200.75,
        "channel": "online"
      }
    }
    ```

    The response's `result` object contains `transaction_id`, `risk_score`, `review_priority`, and `review_indicators`. The endpoint lets the App request scores without loading or training the model.
  </Step>

  <Step title="Preview the App in the Workspace" id="preview-the-app">
    Add `app.py` and `app.sh` to the repository.

    <AccordionGroup>
      <Accordion title="View app.py, preview the Dash App">
        ```python app.py theme={null}
        """Dash App for reviewing synthetic transactions."""

        from __future__ import annotations

        import os
        from pathlib import Path

        import dash_mantine_components as dmc
        import pandas as pd
        import plotly.graph_objects as go
        import requests
        from dash import ALL, Dash, Input, Output, State, callback, ctx, dcc, html

        dmc.pre_render_color_scheme()

        DATASET_DIR = Path(
            os.environ.get("TRANSACTION_REVIEW_DATASET", "/mnt/data/AML")
        )
        DATA_PATH = DATASET_DIR / "transactions.csv"
        TRANSACTIONS = pd.read_csv(DATA_PATH) if DATA_PATH.exists() else pd.DataFrame()
        TRANSACTION_BY_ID = (
            TRANSACTIONS.set_index("transaction_id").to_dict("index")
            if not TRANSACTIONS.empty
            else {}
        )


        def domino_path_prefix() -> str:
            prefix = os.environ.get("DOMINO_RUN_HOST_PATH", "/")
            return f"/{prefix.strip('/')}/" if prefix.strip("/") else "/"


        app = Dash(
            __name__,
            title="Synthetic Transaction Review",
            routes_pathname_prefix="/",
            requests_pathname_prefix=domino_path_prefix(),
        )


        def review_queue():
            if TRANSACTIONS.empty:
                return dmc.Alert(
                    "Run generate_data.py before starting the App.",
                    title="Dataset not found",
                    color="red",
                )
            rows = []
            queue = TRANSACTIONS.sort_values("amount", ascending=False).head(20)
            for transaction in queue.to_dict("records"):
                transaction_id = transaction["transaction_id"]
                rows.append(
                    html.Tr(
                        [
                            html.Td(transaction_id),
                            html.Td(f"${transaction['amount']:,.2f}"),
                            html.Td(transaction["channel"].capitalize()),
                            html.Td(
                                dmc.Button(
                                    "Review",
                                    id={"type": "review-transaction", "index": transaction_id},
                                    variant="light",
                                    size="compact-sm",
                                )
                            ),
                        ]
                    )
                )
            return dmc.Table(
                [
                    html.Thead(
                        html.Tr(
                            [html.Th("Transaction"), html.Th("Amount"), html.Th("Channel"), html.Th("")]
                        )
                    ),
                    html.Tbody(rows),
                ],
                striped=True,
                highlightOnHover=True,
            )


        def transaction_volume_figure(color_scheme="light"):
            template = "plotly_dark" if color_scheme == "dark" else "plotly_white"
            if TRANSACTIONS.empty:
                return go.Figure().update_layout(template=template)
            weekly_volume = (
                TRANSACTIONS.assign(
                    week=pd.to_datetime(TRANSACTIONS["transaction_date"])
                    .dt.to_period("W")
                    .dt.start_time
                )
                .groupby("week", as_index=False)["amount"]
                .sum()
            )
            figure = go.Figure(
                go.Scatter(
                    x=weekly_volume["week"],
                    y=weekly_volume["amount"],
                    fill="tozeroy",
                    hovertemplate="%{x|%b %d}<br>$%{y:,.0f}<extra></extra>",
                )
            )
            figure.update_layout(
                template=template,
                height=300,
                margin=dict(l=0, r=0, t=10, b=0),
                xaxis_title="Week",
                yaxis_title="Volume",
            )
            return figure


        def endpoint_error() -> str | None:
            missing = [
                name
                for name in ("DOMINO_ENDPOINT_URL", "DOMINO_MODEL_ACCESS_TOKEN")
                if not os.environ.get(name)
            ]
            return f"Configure these Project variables: {', '.join(missing)}" if missing else None


        def endpoint_configuration_alert():
            configuration_error = endpoint_error()
            if not configuration_error:
                return None
            return dmc.Alert(
                configuration_error,
                title="Endpoint unavailable",
                color="red",
            )


        @callback(
            Output("transaction-detail", "children"),
            Output("current-transaction", "data"),
            Output("approve-transaction", "disabled"),
            Output("flag-transaction", "disabled"),
            Input({"type": "review-transaction", "index": ALL}, "n_clicks"),
            prevent_initial_call=True,
        )
        def review_transaction(_clicks):
            transaction_id = ctx.triggered_id["index"]
            transaction = TRANSACTION_BY_ID[transaction_id]
            configuration_error = endpoint_error()
            if configuration_error:
                return (
                    dmc.Alert(configuration_error, title="Endpoint unavailable", color="red"),
                    None,
                    True,
                    True,
                )
            payload = {
                "transaction_id": transaction_id,
                "amount": transaction["amount"],
                "counterparty_age_days": transaction["counterparty_age_days"],
                "recent_transaction_count": transaction["recent_transaction_count"],
                "recent_aggregate_amount": transaction["recent_aggregate_amount"],
                "channel": transaction["channel"],
            }
            try:
                response = requests.post(
                    os.environ["DOMINO_ENDPOINT_URL"],
                    auth=(
                        os.environ["DOMINO_MODEL_ACCESS_TOKEN"],
                        os.environ["DOMINO_MODEL_ACCESS_TOKEN"],
                    ),
                    json={"data": payload},
                    timeout=15,
                )
                response.raise_for_status()
                result = response.json()["result"]
            except (requests.RequestException, KeyError, ValueError):
                return (
                    dmc.Alert(
                        "The endpoint did not return a score. Check its status and App logs.",
                        title="Scoring failed",
                        color="red",
                    ),
                    None,
                    True,
                    True,
                )
            detail = dmc.Stack(
                [
                    dmc.Group(
                        [
                            dmc.Title(transaction_id, order=3),
                            dmc.Badge(result["review_priority"], variant="light"),
                        ],
                        justify="space-between",
                    ),
                    dmc.Text(f"Risk score: {result['risk_score']:.2f}", fw=700),
                    dmc.Text(f"Amount: ${transaction['amount']:,.2f}"),
                    dmc.Text("Origin", fw=600),
                    dmc.Text(
                        f"{transaction['origin_address']} · {transaction['origin_country']}"
                    ),
                    dmc.Text("Destination", fw=600),
                    dmc.Text(
                        f"{transaction['destination_address']} · "
                        f"{transaction['destination_country']}"
                    ),
                    dmc.Text("Review indicators", fw=600),
                    html.Ul([html.Li(indicator) for indicator in result["review_indicators"]]),
                ],
                gap="sm",
            )
            return detail, transaction_id, False, False


        @callback(
            Output("transaction-decision", "children"),
            Output("review-decisions", "data"),
            Input("approve-transaction", "n_clicks"),
            Input("flag-transaction", "n_clicks"),
            Input("current-transaction", "data"),
            State("review-decisions", "data"),
            prevent_initial_call=True,
        )
        def record_decision(_approve_clicks, _flag_clicks, transaction_id, decisions):
            decisions = decisions or {}
            if not transaction_id:
                return None, decisions
            if ctx.triggered_id == "approve-transaction":
                decisions = {**decisions, transaction_id: "approved"}
            elif ctx.triggered_id == "flag-transaction":
                decisions = {**decisions, transaction_id: "flagged"}
            decision = decisions.get(transaction_id)
            if not decision:
                return None, decisions
            color = "green" if decision == "approved" else "red"
            return dmc.Alert(f"{transaction_id} {decision} for this session.", color=color), decisions


        @callback(
            Output("transaction-volume", "figure"),
            Input("color-scheme-toggle", "computedColorScheme"),
        )
        def update_chart_theme(color_scheme):
            return transaction_volume_figure(color_scheme)


        app.layout = dmc.MantineProvider(
            dmc.Container(
                dmc.Stack(
                    [
                        dcc.Store(id="current-transaction"),
                        dcc.Store(id="review-decisions", data={}),
                        dmc.Group(
                            [
                                dmc.Title("Synthetic Transaction Review", order=1),
                                dmc.Tooltip(
                                    dmc.ColorSchemeToggle(
                                        id="color-scheme-toggle",
                                        lightIcon="☀",
                                        darkIcon="☾",
                                        size="lg",
                                        **{"aria-label": "Toggle light and dark mode"},
                                    ),
                                    label="Toggle light and dark mode",
                                ),
                            ],
                            justify="space-between",
                        ),
                        endpoint_configuration_alert(),
                        dmc.Grid(
                            [
                                dmc.GridCol(
                                    dmc.Paper(
                                        dmc.Stack(
                                            [dmc.Title("Review queue", order=2), review_queue()],
                                            gap="md",
                                        ),
                                        p="lg",
                                        withBorder=True,
                                    ),
                                    span={"base": 12, "md": 8},
                                ),
                                dmc.GridCol(
                                    dmc.Stack(
                                        [
                                            dmc.Paper(
                                                dmc.Stack(
                                                    [
                                                        html.Div(
                                                            "Select Review to score a transaction.",
                                                            id="transaction-detail",
                                                        ),
                                                        html.Div(id="transaction-decision"),
                                                        dmc.Group(
                                                            [
                                                                dmc.Button(
                                                                    "Approve",
                                                                    id="approve-transaction",
                                                                    color="green",
                                                                    disabled=True,
                                                                ),
                                                                dmc.Button(
                                                                    "Flag",
                                                                    id="flag-transaction",
                                                                    color="red",
                                                                    variant="light",
                                                                    disabled=True,
                                                                ),
                                                            ]
                                                        ),
                                                    ],
                                                    gap="md",
                                                ),
                                                p="lg",
                                                withBorder=True,
                                            ),
                                            dmc.Paper(
                                                dmc.Stack(
                                                    [
                                                        dmc.Title(
                                                            "Transaction volume", order=2
                                                        ),
                                                        dcc.Graph(
                                                            id="transaction-volume",
                                                            figure=transaction_volume_figure(),
                                                            config={"displayModeBar": False},
                                                        ),
                                                    ],
                                                    gap="sm",
                                                ),
                                                p="lg",
                                                withBorder=True,
                                            ),
                                        ],
                                        gap="lg",
                                    ),
                                    span={"base": 12, "md": 4},
                                ),
                            ],
                            gutter="lg",
                        ),
                    ],
                    gap="lg",
                ),
                size="xl",
                py="xl",
            )
        )


        if __name__ == "__main__":
            app.run(host="0.0.0.0", port=8888, debug=False)
        ```
      </Accordion>

      <Accordion title="View app.sh, launch the App">
        ```bash app.sh theme={null}
        #!/usr/bin/env bash
        set -euo pipefail

        python app.py
        ```
      </Accordion>
    </AccordionGroup>

    Commit and push both files. App Preview runs that commit with the selected Environment, Hardware Tier, and Dataset mount before you publish a version.

    Create these Project environment variables. Keep their values out of Git and screenshots.

    ```text theme={null}
    DOMINO_ENDPOINT_URL
    DOMINO_MODEL_ACCESS_TOKEN
    ```

    Open **App Preview** in the Workspace and use `app.sh` as the entry point. Select the tutorial Environment revision and CPU Hardware Tier, and keep the `AML` Dataset mounted.

    Select **Review** beside a transaction to call the endpoint. Select **Approve** or **Flag** to record a decision for the browser session.

    <Frame>
      <img src="https://mintcdn.com/dominodatalab-e871cec4/tAN89q5OuNV-ii4x/images/getting-started/synthetic-transaction-review-preview.png?fit=max&auto=format&n=tAN89q5OuNV-ii4x&q=85&s=6af7b928dbfa16090269db97986bea55" alt="App Preview settings beside the Synthetic Transaction Review App with a scored transaction." width="3078" height="1930" data-path="images/getting-started/synthetic-transaction-review-preview.png" />
    </Frame>
  </Step>

  <Step title="Deploy the App" id="deploy-the-app">
    Publish the Draft App as **Synthetic Transaction Review** and confirm that it includes the `AML` Dataset mount. The immutable version pins the Git commit, entry point, Compute Environment revision, and Dataset configuration. Publishing does not deploy it.

    Select the version, configure its Hardware Tier and audience, then deploy it.

    <Frame>
      <img src="https://mintcdn.com/dominodatalab-e871cec4/tAN89q5OuNV-ii4x/images/getting-started/synthetic-transaction-review-app-overview.png?fit=max&auto=format&n=tAN89q5OuNV-ii4x&q=85&s=01b437529970ff7d455143a2952d8654" alt="Synthetic Transaction Review App overview showing a running version, runtime metrics, Compute Environment, and Hardware Tier." width="3080" height="1910" data-path="images/getting-started/synthetic-transaction-review-app-overview.png" />
    </Frame>

    Open the shared URL and score one transaction. Earlier versions remain available for rollback.

    <Frame>
      <img src="https://mintcdn.com/dominodatalab-e871cec4/tAN89q5OuNV-ii4x/images/getting-started/synthetic-transaction-review-app.png?fit=max&auto=format&n=tAN89q5OuNV-ii4x&q=85&s=a63a796991e290b418fe78b2c266b185" alt="Deployed Synthetic Transaction Review App with a review queue, scored transaction details, decision buttons, and a transaction volume chart." width="3078" height="1930" data-path="images/getting-started/synthetic-transaction-review-app.png" />
    </Frame>

    Stop the Workspace, App, and endpoint when you finish.
  </Step>
</Steps>

## Related

* [Git-based Projects](/cloud/platform-capabilities/core-concepts/projects/git-based-projects)
* [Create and manage Datasets](/cloud/platform-capabilities/core-concepts/data/datasets/create-and-manage-datasets)
* [Deploy Domino endpoints](/cloud/platform-capabilities/features/model-deployment)
* [Develop and test an App](/cloud/platform-capabilities/features/apps/develop-and-test-an-app)
* [Publish and deploy App versions](/cloud/platform-capabilities/features/apps/publish-and-deploy-app-versions)


## Related topics

- [Code examples](/cloud/examples/code-examples.md)
- [Track and monitor experiments](/cloud/platform-capabilities/features/development/track-monitor.md)
- [Advanced Flows](/cloud/platform-capabilities/features/flows/advanced-flows.md)
- [Govern an App](/cloud/platform-capabilities/features/apps/govern-an-app.md)
