Skip to Content

API Reference

Every endpoint below shows a copy-pasteable request body and a sample response. Endpoints are grouped by component.

Workbench2 — two-tower algorithm

Base prefix: /api/v1.

MethodPathSync/Async
GET/algorithms/two-tower/healthsync
GET/algorithms/two-tower/predictorssync
GET/algorithms/two-tower/predictor-date-boundssync
GET/algorithms/two-tower/configssync
POST/algorithms/two-tower/configssync
POST/algorithms/two-tower/configs/{config_id}/prediction-linksync
GET/algorithms/two-tower/configs/{config_id}/jobssync
POST/algorithms/two-tower/trainasync job
POST/algorithms/two-tower/batch-scoreasync job
POST/algorithms/two-tower/export-embeddingsasync job
POST/algorithms/two-tower/concept-testsync

Saved configuration

Request (POST /algorithms/two-tower/configs):

{ "config_id": "customer_offer_retrieval_v1", "name": "Customer Offer Retrieval v1", "engine": "pytorch_notebooks", "source": { "database": "logging", "collection": "ecosystemruntime_flatten", "predictor": "my_predictor", "from_date": "2026-01-01", "to_date": "2026-06-01" }, "features": { "target_column": "accepted", "user_features": ["customer_id", "price", "rank", "score"], "item_features": ["offer", "price", "rank", "score"], "categorical_columns": ["customer_id", "offer"] }, "keys": { "customer_key_field": "customer_id", "offer_key_field": "offer" }, "training": { "embedding_dim": 32, "epochs": 25, "stopping_rounds": 3, "batch_size": 256, "learning_rate": 0.001, "hidden": [128, 64] }, "embedding_export": { "database": "ecosystem_meta", "user_collection": "two_tower_user_embeddings", "item_collection": "two_tower_item_embeddings", "metric": "cosine", "normalized": true } }

Saved configurations are listed in the /two-tower table. Jobs should include context.config_id so the page can show all jobs for the selected config.

The deployable Workbench asset is still a prediction entity. Link or create it from the saved config:

{ "config_id": "customer_offer_retrieval_v1", "predict_id": "customer_offer_retrieval_v1", "create_if_missing": true }

The linked prediction stores compact two_tower metadata while detailed run history remains in two_tower_runs and async jobs.

Train

Request:

{ "config_id": "customer_offer_retrieval_v1", "engine": "h2o", "database": "logging", "flatten_collection": "ecosystemruntime_flatten", "predictor": "my_predictor", "from_date": "2026-01-01", "to_date": "2026-06-01", "embedding_dim": 32, "epochs": 5, "stopping_rounds": 3, "run_id": "tt_abc123" }

Response (job accepted) and final job result:

{ "job_id": "job_789" }
{ "run_id": "tt_abc123", "user_model_id": "two_tower_user_tt_abc123", "item_model_id": "two_tower_item_tt_abc123", "user_auc": 0.72, "item_auc": 0.68, "n_rows": 150000 }

Batch score

Request:

{ "run_id": "tt_abc123", "top_k": 10, "max_users": 5000, "scores_collection": "two_tower_scores" }

Response (per-customer document written to MongoDB):

{ "run_id": "tt_abc123", "customer_id": "user_1", "ranked": [ { "offer": "ProductB", "score": 0.87 }, { "offer": "ProductC", "score": 0.41 } ], "created_at": "2026-06-30T00:00:00Z" }

Export embeddings

Request:

{ "run_id": "tt_abc123", "config_id": "customer_offer_retrieval_v1", "embedding_database": "ecosystem_meta", "user_embedding_collection": "two_tower_user_embeddings", "item_embedding_collection": "two_tower_item_embeddings", "customer_key_field": "customer_id", "offer_key_field": "offer", "max_users": 100000, "max_items": 100000 }

Accepted response:

{ "job_id": "job_export_123", "message": "Embedding export started" }

Final job result:

{ "run_id": "tt_abc123", "config_id": "customer_offer_retrieval_v1", "embedding_database": "ecosystem_meta", "user_embedding_collection": "two_tower_user_embeddings", "item_embedding_collection": "two_tower_item_embeddings", "user_embedding_count": 240000, "item_embedding_count": 5800, "embeddings_exported_at": "2026-06-30T00:00:00Z" }

Concept test

Request:

{ "run_id": "tt_abc123", "customer_id": "user_1", "offers": ["ProductA", "ProductB"] }

Response:

{ "success": true, "run_id": "tt_abc123", "customer_id": "user_1", "ranked": [ { "offer": "ProductB", "score": 0.87 }, { "offer": "ProductA", "score": 0.12 } ] }

ecosystem-notebooks — PyTorch sidecar

Base URL: http://<notebooks-host>:8010.

MethodPathPurpose
POST/pytorch/traintrain MLP or two-tower model
POST/pytorch/invocationsscore / embed by model_id
GET/pytorch/modelslist trained model ids
GET/pytorch/healthhealth check

Train

Request:

{ "model_id": "customer_offer_retrieval_v1", "model_type": "two_tower", "async": true, "problem_type": "binary_classification", "data": { "source": { "database": "logging", "collection": "ecosystemruntime_flatten", "pipeline": [ { "$match": { "predictor": "my_predictor" } }, { "$project": { "_id": 0, "customer_id": 1, "offer": 1, "price": 1, "rank": 1, "score": 1, "accepted": 1 } } ], "limit": 100000 }, "csv_path": null, "inline": null, "target_column": "accepted", "categorical_columns": ["customer_id", "offer"], "train_test_split": 0.2, "random_state": 42 }, "hyperparameters": { "epochs": 25, "batch_size": 256, "hidden": 64, "learning_rate": 0.001, "embedding_dim": 32, "user_features": ["customer_id", "price", "rank", "score"], "item_features": ["offer", "price", "rank", "score"], "user_id_column": "customer_id", "item_id_column": "offer" } }

Response:

{ "run_id": "run_2f1c", "status": "succeeded", "model_id": "two_tower_user_v1", "metrics": { "user_auc": 0.71, "item_auc": 0.67 }, "rows_total": 100000 }

Invocations (score / embed)

Request:

{ "model_id": "customer_offer_retrieval_v1", "instances": [ { "customer_id": "user_1", "price": 0, "rank": 1, "score": 0, "tower": "user" } ] }

Response:

{ "predictions": [ { "prediction": 0.87, "embedding": [0.11, 0.20, 0.07] } ], "final_result": [ { "prediction": 0.87, "embedding": [0.11, 0.20, 0.07] } ], "framework": "pytorch" }

ApiModelClient.embed() accepts the embedding at predictions[0].embedding, or top-level embedding / vector / outputs[0].

Python runner

The scriptable flow should call the same Workbench APIs as the UI:

python backend/scripts/two_tower_pipeline.py \ --config-id customer_offer_retrieval_v1 \ --steps train,concept-test,export-embeddings \ --wait

Expected JSON output:

{ "config_id": "customer_offer_retrieval_v1", "run_id": "tt_abc123", "jobs": [ { "step": "train", "job_id": "job_train_1", "status": "Completed" }, { "step": "export-embeddings", "job_id": "job_export_1", "status": "Completed" } ], "embedding_export": { "database": "ecosystem_meta", "user_collection": "two_tower_user_embeddings", "item_collection": "two_tower_item_embeddings", "user_embedding_count": 240000, "item_embedding_count": 5800 }, "deployment_properties": { "predictor.model.type": "similarity", "predictor.twotower.run.id": "tt_abc123" } }

ecosystem-runtime — invocations

Request (POST /invocate):

{ "campaign": "two_tower_demo", "sub-campaign": "default", "channel": "web", "customer": "user_1", "numberoffers": 3, "userid": "ecosystem", "in_params": { "input": ["customer_id"], "value": ["user_1"] } }

Response (trimmed):

{ "final_result": [ { "rank": 1, "result": { "offer": "ProductB", "offer_name": "ProductB", "score": 0.87 } }, { "rank": 2, "result": { "offer": "ProductC", "offer_name": "ProductC", "score": 0.41 } } ], "explore": 0, "uuid": "..." }
Last updated on