Managing Strategies
The workflow is: create a group, add strategies, activate. Groups are born as drafts and nothing bids until activation, so you can assemble and review the whole portfolio before any demand goes live.
Creating a group
mutation C($i: CreateBiddingStrategyGroupInput!) {
createBiddingStrategyGroup(input: $i) {
group { id name groupType isActive isDraft maxGroupSpendCents createdAt }
error { message code }
}
}
{
"i": {
"assetTypeId": "5e78b0f7-e476-48fe-bb8d-31a7f79523ab",
"name": "PSA 10 Strategy",
"maxGroupSpendCents": 10000000,
"data": {
"variance": { "belowFv": { "unit": "PCT", "value": 0.15 } },
"fillMode": "DEFAULT"
}
}
}
| Field | Type | Required | Description |
|---|---|---|---|
assetTypeId | ID | Yes | Asset type this group targets — see Verticals |
name | String | Yes | Human-readable name |
groupType | BiddingStrategyGroupType | No | STANDARD (default) |
description | String | No | Free-form description |
data | StandardGroupData | No | Pricing defaults, fill mode, market scope — see Pricing and Types |
externalReferenceId | String | No | Your reference ID. Unique per account — a duplicate returns DUPLICATE_REFERENCE |
recipientAddressId | ID | No | Saved ship-to for fills — see Address Management |
paymentTokenId | ID | No | Saved payment method charged when strategies fill |
paymentRail | PaymentRail | No | CARD, ACH, WIRE, TRADEPOST_BALANCE |
maxGroupSpendCents | Int | No | Aggregate spend cap across all child strategies |
maxUnitQuantity | Int | No | Aggregate unit cap across all child strategies |
maxFillsPerConfig | Int | No | Per-product fill-count cap within the group |
maxSpendPerConfigCents | Int | No | Per-product spend cap — bounds concentration in any single product regardless of fill count |
New groups start isDraft: true, isActive: false.
Adding strategies
mutation A($i: AddStrategyToGroupInput!) {
addStrategyToGroup(input: $i) {
group { id biddingStrategies { id name isActive } }
error { message code }
}
}
{
"i": {
"groupId": "<groupId>",
"name": "PSA 10 — CardHedge",
"strategyConfig": {
"filterCriteria": {
"fvModelConfigId": "<fvModelConfigId>",
"keyCriteria": [
{ "fvKeyIds": ["<PSA 10 keyId>"], "requiredKeyIds": [] }
],
"fvMinCents": 10000,
"fvMaxCents": 100000,
"fvConfidenceMin": 0.7,
"facets": { "include": { "asset_data.subcategory": ["POKEMON_CARDS"] } }
},
"variance": { "belowFv": { "unit": "PCT", "value": 0.20 } },
"targetQuantity": 50
}
}
}
| Field | Type | Required | Description |
|---|---|---|---|
groupId | ID | Yes | Parent group |
name | String | Yes | Strategy name |
description | String | No | Free-form description |
strategyConfig | GroupedStrategyConfig | Yes | Targeting + pricing — targeting below, pricing in Pricing |
maxStrategySpendCents | Int | No | Per-strategy spend cap |
maxUnitQuantity | Int | No | Per-strategy unit cap |
New strategies are inactive until the group is activated (or setStrategyStatus activates them individually).
Targeting
strategyConfig.filterCriteria defines what a strategy buys. Filters re-evaluate every time the strategy runs, so a strategy tracks the catalog rather than a fixed product list.
Grade targeting
keyCriteria selects graded variants. Evaluation is OR across criteria, AND within one: an item satisfies the strategy if any single criterion passes in full, and a criterion passes when the item carries every key in both fvKeyIds and requiredKeyIds. The bid prices against the highest fair value across the criterion's fvKeyIds.
Bid on multiple grades — one criterion per grade:
{
"keyCriteria": [
{ "fvKeyIds": ["<PSA 10 keyId>"], "requiredKeyIds": [] },
{ "fvKeyIds": ["<PSA 9 keyId>"], "requiredKeyIds": [] }
]
}
Require an autograph grade alongside the card grade — requiredKeyIds adds the AND gate:
{
"keyCriteria": [
{ "fvKeyIds": ["<PSA 9 keyId>"], "requiredKeyIds": ["<PSA Auto 9 keyId>"] }
]
}
Discover key IDs via Catalog → Keys.
The matcher skips strategies with no matching criterion. A strategy without keyCriteria never bids.
Attribute filters
facets— include/exclude products by attribute value:{ "include": { "asset_data.subcategory": ["POKEMON_CARDS"] }, "exclude": { "data.rarity": ["Common"] } }. Discover valid fields and values — and preview what a filter matches — via the Filter Builder.facetRanges— numeric bounds per numeric facet field, applied on top offacets:{ "asset_data.release_year": { "greaterThanOrEqual": 2015, "lessThanOrEqual": 2020 } }. Bound keys:greaterThan,greaterThanOrEqual,lessThan,lessThanOrEqual, orequalToalone. A product with no value for the field does not match. Date fields take epoch seconds, not calendar years.excludedAssetConfigIds— a deny-list of specific product configuration IDs: "everything in this filter except these". Use it to drop known products by ID; usefacets.excludeto drop by attribute.query— optional text query.- Fair-value bounds —
fvMinCents/fvMaxCents/fvConfidenceMinrestrict matching to products whose fair value and model confidence are in range.VARIANCEmode only — see Pricing.
Tuning a live group
updateBiddingStrategyGroup touches only the fields you pass. Pricing-default changes propagate to every strategy that inherits them; strategies with their own variance override are unaffected. Updatable: name, description, data, fulfillment fields, and all four caps.
updateGroupedStrategy (by groupId + strategyId) replaces a strategy's strategyConfig, caps, or name in place — filters and pricing change without recreating the strategy or losing its fill history.
removeStrategyFromGroup detaches and deactivates one strategy.
Lifecycle
Drive state with two mutations: setBiddingStrategyGroupStatus for the group, setStrategyStatus for one strategy within it.
mutation S($i: SetBiddingStrategyGroupStatusInput!) {
setBiddingStrategyGroupStatus(input: $i) {
group { id isActive isDraft pausedAt deletedAt }
error { message code }
}
}
{ "i": { "groupId": "<groupId>", "action": "ACTIVATE" } }
| Action | Allowed when | Effect |
|---|---|---|
ACTIVATE | Draft, or paused | Activates every child strategy; requires at least one strategy attached. Clears the draft flag |
PAUSE | Active, not draft | Deactivates every child strategy, stamps pausedAt |
RESUME | Paused, not draft | Reactivates every child strategy, clears pausedAt |
DELETE | Any state | Deactivates all children and soft-deletes the group |
setStrategyStatus takes groupId, strategyId, and ACTIVATE or DEACTIVATE. Activating a strategy inside an active group puts it to work immediately.
Activation is also what creates each strategy's identity submission; deactivation cancels it. You never manage that submission directly:
Each active strategy owns one system-managed order submission. updateOrderSubmission and cancelOrderSubmission against it return SIGMAFILL_MANAGED, and bulkCancelOrderSubmissions skips it — including the empty-input cancel-everything form. Control strategy demand through the strategy lifecycle, not the submission APIs.
Querying groups
getBiddingStrategyGroup fetches one group; pass includeStrategies: true to hydrate children. listBiddingStrategyGroups pages the account's groups with assetTypeId / isActive filters and standard limit-offset pagination.
query G($i: GetBiddingStrategyGroupInput!) {
getBiddingStrategyGroup(input: $i) {
group {
name
isActive
maxGroupSpendCents
currentGroupSpendCents
pendingGroupSpendCents
biddingStrategies { id name isActive currentStrategySpendCents }
}
error { message code }
}
}
The current* / pending* counters are how you watch consumption against caps — see Fills → Budget accounting.
Deleting
deleteBiddingStrategyGroup (or the DELETE lifecycle action — they're equivalent) soft-deletes the group and deactivates all children. The row is hard-deleted by a cleanup job after the retention window.