Archana Garikapati
08/21/2025, 4:36 PMMarvin
08/21/2025, 4:36 PMMarvin
08/21/2025, 4:39 PMMarvin
08/21/2025, 4:39 PMBrendan Dalpe
08/21/2025, 4:41 PMMarvin
08/21/2025, 4:41 PMprefect deployment ls
) will not show it after deletion.
- Direct lookups by ID (or some API filter calls) can still return the deployment object, typically with a deleted
timestamp/flag set.
Why Prefect does this:
- It preserves run history and references for auditability and troubleshooting.
- It avoids breaking links from historical flow runs or artifacts that reference the deployment.
How to confirm:
- If you’re calling the REST API by ID, check the response for a deleted
field/timestamp. That indicates the object is soft-deleted.
- If you’re listing via API and still seeing it, you may be using a filter or parameter that includes deleted records. Make sure you’re not opting into “include deleted” behavior.
A couple of questions to help us zero in:
- How are you querying the API when you still see it (endpoint or client method)?
- Are you on Prefect Cloud or a self-hosted server?
- Did you delete via the UI or prefect deployment delete
? Approximately when?
If you truly need the deployment fully purged:
- Self-hosted: you’d need to perform a hard delete at the database level (recommended only if you know the implications).
- Prefect Cloud: let us know and we can route you to support for assistance.
Share the endpoint you’re hitting and a snippet of the response (with IDs redacted if needed) and I’ll help confirm the deleted
flag and suggest the exact filter to hide it.Marvin
08/21/2025, 4:44 PMArchana Garikapati
08/21/2025, 4:47 PMMarvin
08/21/2025, 4:47 PMMarvin
08/21/2025, 4:47 PMdeleted
field (or a status indicating it’s deleted). UI and prefect deployment ls
hide those by default.
- If you’re filtering broadly (e.g., by name/tags), the filter endpoint may return the record even if it’s soft-deleted; you’ll need to exclude it client-side by checking deleted is None
.
- Another common case: there are multiple deployments with the same flow/deployment name. You may have deleted one, but your filter is returning a different, still-active deployment with the same name.
Quick checks to pinpoint it:
1) Inspect the response for the deployment in question and look for `deleted`:
- If deleted
is non-null, the object is soft-deleted; filter it out in your client:
[d for d in deployments if not d.get("deleted")]
- If deleted
is null, it wasn’t deleted — confirm you deleted the right ID.
2) Fetch by ID to confirm the record’s state:
- GET:
/api/accounts/{account_id}/workspaces/{workspace_id}/deployments/{deployment_id}
- If this returns deleted
not null, the delete succeeded and you’re just seeing a soft-deleted record in your filter response.
3) Double-check with the CLI (should exclude deleted by default):
prefect deployment ls
If the CLI doesn’t show it but the filter endpoint returns it with deleted: null
, that’s unexpected — please share the request body you’re posting to /deployments/filter
and a redacted sample of the returned item so I can reproduce and escalate.
If you can share:
- The POST body you send to /deployments/filter
- The specific deployment ID and whether its response shows deleted
I’ll give you the exact filter or a workaround, and open an issue if it’s a bug.Marvin
08/21/2025, 4:51 PM/deployments/filter
is still returning it, either:
- the response includes the soft-deleted record (likely with a `deleted`/`deleted_at` timestamp), or
- there’s an edge case/bug with the filter endpoint for your workspace.
Can you share:
- The exact POST body you’re sending to /deployments/filter
- A redacted example of one returned deployment (id/name + any `deleted`/`deleted_at` field if present)
Quick checks you can run:
1) Try a direct GET by id. A soft-deleted deployment should generally not be returned by ID.
curl -H "Authorization: Bearer <API_KEY>" \
<https://api.prefect.cloud/api/accounts/<ACCOUNT_ID>/workspaces/<WORKSPACE_ID>/deployments/<DEPLOYMENT_ID>>
- If this returns 404, it’s deleted; your filter call is just including it somehow.
- If it returns 200 with the object, check for a `deleted`/`deleted_at` field.
2) If your filter response includes a deleted
field, filter it out client-side as a workaround:
active = [d for d in deployments if not d.get("deleted") and not d.get("deleted_at")]
Reference docs for the deployments endpoints:
- Read deployments (REST API)
If you share the POST body and a response sample, I’ll help pinpoint the exact filter/behavior. If the endpoint is returning soft-deleted items without any way to exclude them (and no deleted
field in the response), I can escalate this to our Cloud team with your workspace and deployment IDs.Archana Garikapati
08/21/2025, 5:45 PMMarvin
08/21/2025, 5:45 PMMarvin
08/21/2025, 5:46 PMGET /api/accounts/{account_id}/workspaces/{workspace_id}/deployments/{deployment_id}
If it returns 404, it was deleted; your filter request is returning a different deployment. If it returns 200, check if the payload includes a deleted
or deleted_at
timestamp.
2) Narrow your filter to a specific ID
Post this to your current endpoint to ensure we’re querying a single deployment:
POST /api/accounts/{account_id}/workspaces/{workspace_id}/deployments/filter
{
"deployments": {
"id": {
"any_": ["<deployment_id>"]
}
},
"limit": 100
}
3) If you’re filtering by name, check for dupes
It’s common to have multiple deployments with the same name (different flows or versions). Try:
{
"deployments": {
"name": {
"any_": [
"<deployment_name>"
]
}
}
}
Compare the IDs returned to the one you deleted.
4) As a quick sanity check with the CLI (excludes deleted by default):
prefect deployment inspect "<flow_name>/<deployment_name>"
- If the CLI can still inspect it, it’s not deleted.
- If inspect fails, you’re likely querying a different deployment via the API.
Docs for the deployments endpoint:
- Read deployments (REST API)
If you can share:
- The POST body you’re sending to /deployments/filter
- One returned item (id/name/status and any `deleted`/`deleted_at` field), redacted as needed
…I’ll pinpoint whether this is a duplicate-name case, a filter quirk, or something we should escalate.Marvin
08/21/2025, 6:36 PMMarvin
08/21/2025, 6:37 PM/deployments/filter
endpoint expects filter objects under top-level keys like deployments
, flows
, etc., with operators such as any_
or like_
.
Try one of these:
- Exact deployment name match
curl -X POST "<https://api.prefect.cloud/api/accounts/<ACCOUNT_ID>/workspaces/<WORKSPACE_ID>/deployments/filter>" \
-H "Authorization: Bearer <API_KEY>" \
-H "Content-Type: application/json" \
-d '{
"limit": 200,
"offset": 0,
"sort": "UPDATED_DESC",
"deployments": {
"name": { "any_": ["da_gen_e"] }
}
}'
- Partial match on flow OR deployment name
{
"limit": 200,
"offset": 0,
"sort": "UPDATED_DESC",
"deployments": {
"flow_or_deployment_name": {
"like_": "da_gen_e"
}
}
}
- Match both a specific flow and deployment name (prevents collisions on shared names)
{
"limit": 200,
"offset": 0,
"sort": "UPDATED_DESC",
"flows": {
"name": {
"any_": [
"<flow_name>"
]
}
},
"deployments": {
"name": {
"any_": [
"da_gen_e"
]
}
}
}
- By deployment ID (best for verifying deletion)
{
"deployments": {
"id": {
"any_": [
"<DEPLOYMENT_ID>"
]
}
}
}
Notes:
- Deletions are soft-deletes; the list endpoint should exclude deleted records by default. If you filter by the specific deployment ID and still see “status: ready”, you’re looking at an active (not-deleted) record — likely a different deployment with the same name.
- If a GET by ID returns 404, the deletion succeeded and your broader filter was catching a different record.
REST API reference:
- Read deployments (REST API)
If this still returns the deleted item, paste the request body you used and a redacted snippet of the returned item (id/name/status), and I’ll dig deeper.Archana Garikapati
08/21/2025, 6:40 PMMarvin
08/21/2025, 6:40 PMMarvin
08/21/2025, 6:41 PMcurl -sS -i -H "Authorization: Bearer <API_KEY>" -H "Content-Type: application/json" \
-d '{"limit":50,"deployments":{"name":{"any_":["da_gen_e"]}}}' \
<https://api.prefect.cloud/api/accounts/<ACCOUNT_ID>/workspaces/<WORKSPACE_ID>/deployments/filter>
Common gotchas to check:
- Remove angle brackets from the URL in the actual command. Use plain https://… not <https://…>.
- Don’t use a large offset unless you need it. If there are fewer than offset results, you’ll get an empty page. Start with "offset": 0
or omit it.
- The JSON schema must nest filters under deployments
, flows
, etc. A body like {"filters": {"name": "..."}}
will be ignored by the server.
Minimal working examples:
- Exact deployment name
{
"limit": 50,
"deployments": {
"name": {
"any_": [
"da_gen_e"
]
}
}
}
- Partial match on flow OR deployment name
{
"limit": 50,
"deployments": {
"flow_or_deployment_name": {
"like_": "da_gen_e"
}
}
}
Direct GET by ID (to confirm deletion state):
curl -sS -i -H "Authorization: Bearer <API_KEY>" \
<https://api.prefect.cloud/api/accounts/<ACCOUNT_ID>/workspaces/<WORKSPACE_ID>/deployments/<DEPLOYMENT_ID>>
- 404 = deleted, your filter was catching something else.
- 200 = still present; check the payload for any deleted/deleted_at field and the status you saw (“ready”).
CLI cross-check (excludes deleted):
prefect deployment ls | grep -i da_gen_e || true
If you can share the HTTP status code and the first lines of the response headers/body from the -i
call, I’ll pinpoint the next step. Also please rotate the API key you posted earlier if it’s still active.