Skip to main content

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"
}
}
}
FieldTypeRequiredDescription
assetTypeIdIDYesAsset type this group targets — see Verticals
nameStringYesHuman-readable name
groupTypeBiddingStrategyGroupTypeNoSTANDARD (default)
descriptionStringNoFree-form description
dataStandardGroupDataNoPricing defaults, fill mode, market scope — see Pricing and Types
externalReferenceIdStringNoYour reference ID. Unique per account — a duplicate returns DUPLICATE_REFERENCE
recipientAddressIdIDNoSaved ship-to for fills — see Address Management
paymentTokenIdIDNoSaved payment method charged when strategies fill
paymentRailPaymentRailNoCARD, ACH, WIRE, TRADEPOST_BALANCE
maxGroupSpendCentsIntNoAggregate spend cap across all child strategies
maxUnitQuantityIntNoAggregate unit cap across all child strategies
maxFillsPerConfigIntNoPer-product fill-count cap within the group
maxSpendPerConfigCentsIntNoPer-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
}
}
}
FieldTypeRequiredDescription
groupIdIDYesParent group
nameStringYesStrategy name
descriptionStringNoFree-form description
strategyConfigGroupedStrategyConfigYesTargeting + pricing — targeting below, pricing in Pricing
maxStrategySpendCentsIntNoPer-strategy spend cap
maxUnitQuantityIntNoPer-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.

keyCriteria is required to fill

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 of facets: { "asset_data.release_year": { "greaterThanOrEqual": 2015, "lessThanOrEqual": 2020 } }. Bound keys: greaterThan, greaterThanOrEqual, lessThan, lessThanOrEqual, or equalTo alone. 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; use facets.exclude to drop by attribute.
  • query — optional text query.
  • Fair-value boundsfvMinCents / fvMaxCents / fvConfidenceMin restrict matching to products whose fair value and model confidence are in range. VARIANCE mode 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" } }
ActionAllowed whenEffect
ACTIVATEDraft, or pausedActivates every child strategy; requires at least one strategy attached. Clears the draft flag
PAUSEActive, not draftDeactivates every child strategy, stamps pausedAt
RESUMEPaused, not draftReactivates every child strategy, clears pausedAt
DELETEAny stateDeactivates 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:

The identity submission is read-only

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.