Skip to content

`GET /v1/orgs/{org}/proposals`.

GET
/v1/orgs/{org}/proposals
curl --request GET \
--url https://api.updawg.net/v1/orgs/example/proposals

Newest first, ?status= repeatable, keyset-paginated on ?after=.

No status means every status

Including one this build does not recognise. The temptation is to default an inbox to the open ones — and a default that hides rows is a default that makes a proposal somebody is waiting on invisible without saying so. The portal asks for what it wants to show; the API does not decide on its behalf.

⚠️ Why the query is a list of pairs and not a struct

Query<T> deserialises with serde_urlencoded, which cannot put a repeated key into a Vec. ?status=open&status=snoozed against a Vec<String> field does not collect two values — it fails, and it fails with axum’s own plain-text 400, which carries no type for a portal to branch on and is a different shape from every other refusal this API makes. That is DAWG-246’s problem arriving by a second route.

Vec<(String, String)> is what serde_urlencoded does support, so the pairs are read and interpreted here. It buys one more thing worth having: an unknown parameter can be refused. ?staus=open silently returning everything is the same failure as an unparseable status silently returning everything, and both are a list that is quietly not what was asked for.

org
required
string

Organization slug.

status
Array<string>

Repeatable. Omitted means every status, including one this build does not recognise — a default that hides rows hides the proposal somebody is waiting on.

after
string

The prp_… id of the last proposal on the previous page.

A page, newest first.

Media typeapplication/json
object
next

Pass as ?after= for the next page. Absent at the end, so a client stops rather than asking for a page it has been told is empty.

string | null
proposals
required
Array<object>
object
approvals
required
integer format: int64
auto_merge
required
boolean
closed_at
string | null format: date-time
created_at
required
string format: date-time
hosts
required
integer format: int64
id
required
string
kind
required
string
known_exploited
required

Something it fixes is on CISA’s Known Exploited Vulnerabilities list (DAWG-72). Shown beside the severity; it never raises it.

boolean
max_severity

null means nothing in this proposal was rated, which is not the same as harmless.

string | null
number
required

The #142 people say out loud.

integer format: int32
outstanding
required

Zero for anything final, whatever the counts say — see [db::inbox::Summary::outstanding].

integer format: int64
packages
required

Distinct packages, not proposal_items rows.

integer format: int64
required
required
integer format: int64
scheduled_for
string | null format: date-time
snoozed_until
string | null format: date-time
status
required

A status this build does not recognise is passed through as stored rather than hidden or guessed at. A portal should render an unknown status as unknown — it means this API is older than the thing that wrote the row, which is a deployment fact worth seeing.

string
title
required
string
updated_at
required
string format: date-time
total
required

How many match the filter, not how many are in this page.

integer format: int64
Examplegenerated
{
"next": "example",
"proposals": [
{
"approvals": 1,
"auto_merge": true,
"closed_at": "2026-04-15T12:00:00Z",
"created_at": "2026-04-15T12:00:00Z",
"hosts": 1,
"id": "example",
"kind": "example",
"known_exploited": true,
"max_severity": "example",
"number": 1,
"outstanding": 1,
"packages": 1,
"required": 1,
"scheduled_for": "2026-04-15T12:00:00Z",
"snoozed_until": "2026-04-15T12:00:00Z",
"status": "example",
"title": "example",
"updated_at": "2026-04-15T12:00:00Z"
}
],
"total": 1
}

An unknown status, an unknown parameter, or a cursor naming nothing.

Media typeapplication/json
object
detail
string | null
status
required
integer format: int32
title
required
string
type
required
string
Examplegenerated
{
"detail": "example",
"status": 1,
"title": "example",
"type": "example"
}

No session.

Media typeapplication/json
object
detail
string | null
status
required
integer format: int32
title
required
string
type
required
string
Examplegenerated
{
"detail": "example",
"status": 1,
"title": "example",
"type": "example"
}

No such organization, or not yours.

Media typeapplication/json
object
detail
string | null
status
required
integer format: int32
title
required
string
type
required
string
Examplegenerated
{
"detail": "example",
"status": 1,
"title": "example",
"type": "example"
}

Over the organization’s request limit. Retry-After says when to try again; RateLimit-Limit is the burst.

Media typeapplication/json
object
detail
string | null
status
required
integer format: int32
title
required
string
type
required
string
Examplegenerated
{
"detail": "example",
"status": 1,
"title": "example",
"type": "example"
}