Gotchas

Known Metronome gotchas and the rules that cover them.

View .md

Known Metronome traps, each mapped to the validator rule that covers it, or marked as a gap.

Source

Generated from metro docs gotcha-reference --markdown in metrocli/metro @146bf3e. Source schemaVersion: metro.docs.gotcha-reference.v1.

  • schemaVersion: metro.docs.gotcha-reference.v1

Summary

{
  "gotchaCount": 59,
  "coveredCount": 58,
  "partialCount": 0,
  "openQuestionCount": 0,
  "coverageStatusCounts": {
    "covered": 58,
    "open": 1
  },
  "categoryCounts": {
    "Tenant And Authentication": 4,
    "Endpoint And Method Shape": 4,
    "Packages": 7,
    "Contracts": 4,
    "Billing Provider And Stripe": 4,
    "Customers": 6,
    "Subscriptions": 4,
    "Rate Cards And Products": 8,
    "Credits And Commits": 5,
    "Invoices": 4,
    "Usage Ingest": 3,
    "Bulk Workflows": 3,
    "Repo Hygiene": 3
  }
}

Gotchas

idcategorycoverageStatusgotcha
tenant-selected-by-keyTenant And AuthenticationcoveredProduction and sandbox share the same Metronome base URL; the API key selects the tenant.
env-file-not-authorizationTenant And AuthenticationcoveredA local .env file or existing key is not authorization.
never-infer-production-from-key-presenceTenant And AuthenticationcoveredLoading both production and sandbox keys is common; the CLI must never infer production from key presence.
fingerprints-not-key-valuesTenant And AuthenticationcoveredPrint key fingerprints, never key values.
read-endpoints-can-be-postEndpoint And Method ShapecoveredMany Metronome read endpoints are POST.
get-endpoints-can-use-query-parametersEndpoint And Method ShapecoveredSome list/get endpoints are GET with query parameters.
verify-endpoint-before-implementationEndpoint And Method ShapecoveredBefore implementing any endpoint, verify it against the local endpoint matrix and current Metronome docs.
do-not-guess-endpoint-pathsEndpoint And Method ShapecoveredDo not guess endpoint paths from names.
package-contract-restricted-payloadPackagescoveredPackage-based contract create accepts a restricted payload; extras such as commits or overrides belong in separate edit workflows.
normalize-package-uniqueness-prefixPackagescoveredPackage uniqueness_key may be returned with a package: prefix; normalize before comparing.
package-alias-resolution-at-starting-atPackagescoveredPackage alias resolution depends on the contract starting_at, not when the command runs.
do-not-archive-old-package-before-alias-livePackagescoveredDo not archive the old package version until the new alias is live and verified.
package-plan-move-renewal-two-stepPackagescoveredPackage plan moves should use updateEndDate, then create a successor with transition.type RENEWAL; package contracts do not support SUPERSEDE.
move-plan-requires-open-ended-predecessorContractscoveredmetro contract move-plan preflight requires exactly one open-ended contract (no ending_before); active trials and expired customers do not qualify.
expired-contract-rebuy-no-transitionContractsopenExpired contracts (ending_before in the past) must rebuy via fresh contracts/create without a transition block; do not pass RENEWAL from_contract_id on lapsed predecessors.
renewal-transition-active-handoff-onlyContractscoveredRENEWAL transitions are for active predecessor handoffs where successor starting_at aligns with predecessor ending_before; not for rebuy after lapse.
free-trial-package-duration-expiryPackagescoveredPackage duration (DAYS) generates contract ending_before at provision; trial expiry is not a separate job.
free-zero-rollover-on-rebuyContractscoveredFree trials use rollover_fraction 0; RENEWAL on rebuy carries no useful credits - prefer fresh create when predecessor is expired.
package-plan-move-billing-day-realignmentPackagescoveredBilling-day realignment with charge today uses package-plan-move-immediate-invoice: review paid-period overlap (refund vs no refund) before current-hour cutover.
billable-workflow-requires-billing-providerBilling Provider And StripecoveredBillable customer or contract workflows must prove billing provider config.
stripe-delivery-behavior-explicitBilling Provider And StripecoveredStripe delivery behavior must be explicit: push to Stripe, keep draft, or no Stripe side effect expected.
billing-provider-archive-replace-riskBilling Provider And StripecoveredArchiving or replacing billing provider configs can affect invoice delivery.
multi-entity-stripe-fields-not-guessedBilling Provider And StripecoveredMulti-entity Stripe delivery needs endpoint-specific fields and should not be guessed.
customer-lookup-is-getCustomerscoveredCustomer lookup and search use GET paths with query parameters, not POST customer list payloads.
customer-resolve-name-must-not-full-scanCustomerscoveredName/external-id customer resolve must not paginate the entire /v1/customers list; stop at first exact hit and route email-shaped names through ingest_alias.
customer-ingest-alias-collisionsCustomerscoveredingest_aliases are globally unique per tenant, and archived customers can keep aliases pinned.
customer-set-ingest-aliases-replacesCustomerscoveredsetIngestAliases replaces the full alias list; it is not additive.
customer-hierarchy-lives-on-contractsCustomerscoveredHierarchy is not a customer field; parent/child links live on contracts via hierarchy_configuration.
customer-custom-field-whitelistCustomerscoveredCustomer custom-field keys are allowlisted per entity type and values are limited to 200 characters.
subscription-config-compatibilitySubscriptionscoveredSubscription invoicing requires compatible subscription configuration, not just a product and rate.
subscription-billing-frequency-alignmentSubscriptionscoveredBilling frequency must align across rate-card setup and contract/subscription setup.
subscription-rate-identitySubscriptionscoveredProduct ID and billing frequency together may identify the intended subscription rate.
subscription-quantity-seat-sourceSubscriptionscoveredQuantity or seat source must be explicit.
product-archive-does-not-remove-rate-card-entryRate Cards And ProductscoveredProduct archive does not remove active rate-card entries.
retirement-requires-entitled-falseRate Cards And ProductscoveredRetiring a product requires closing rate entries with entitled:false before archive.
scheduled-product-update-readbackRate Cards And ProductscoveredScheduled product updates may need the endpoint that exposes version history or schedule for verification.
dimensional-metric-compound-group-keyRate Cards And ProductscoveredDimensional action pricing must use one compound billable-metric group key for action_code and action_display_name.
dimensional-one-product-not-per-actionRate Cards And ProductscoveredDimensional action pricing should use one USAGE product with pricing_group_key, not one product per action.
dimensional-scope-four-tier-cardsRate Cards And ProductscoveredMulti-tier dimensional rollout means four tier cards (payg, core, select, pro) - not every rate card in the tenant.
dimensional-metro-route-firstRate Cards And ProductscoveredFor new action codes, run metro route and metro docs explain rate-cards.dimensional, then metro dimensional new-code for production apply.
starting-at-hour-boundaryRate Cards And Productscoveredstarting_at values must be hour-boundary timestamps.
access-schedule-credit-type-is-access-creditCredits And Commitscoveredaccess_schedule.credit_type_id is the product/access credit type for usage.
invoice-schedule-fiat-credit-typeCredits And Commitscoveredinvoice_schedule.credit_type_id must be a fiat currency when present.
complimentary-grant-omit-invoice-scheduleCredits And CommitscoveredComplimentary grants should omit invoice_schedule unless a deliberate zero-dollar audit line is required.
paid-topup-invoice-stripe-behaviorCredits And CommitscoveredPaid top-ups must state invoice and Stripe behavior before preview or apply.
custom-field-keys-approvedCredits And CommitscoveredCustom-field keys must be approved for the target object type.
past-dated-scheduled-charges-finalizeInvoicescoveredPast-dated scheduled charges can finalize immediately.
metronome-void-does-not-refund-stripeInvoicescoveredVoiding in Metronome does not refund Stripe.
archive-with-voiding-reconciliation-gapInvoicescoveredArchiving contracts or customers with invoice voiding can create reconciliation gaps.
invoice-issue-date-stripe-behaviorInvoicescoveredInvoice issue-date changes must include expected Stripe behavior.
historical-usage-finalized-period-riskUsage IngestcoveredHistorical usage can alter finalized-period economics or create follow-up billing effects.
usage-transaction-id-idempotencyUsage IngestcoveredTransaction IDs must be stable for idempotency.
bulk-ingest-canary-period-targetUsage IngestcoveredBulk ingest needs a canary and a clear invoice-period target.
dry-run-not-metronome-write-proofBulk WorkflowscoveredDry-run does not prove every Metronome write validator will accept a payload.
bulk-writes-need-manifest-canary-readbackBulk WorkflowscoveredBulk writes need preview, manifest, canary, read-back verification, and resumable audit log.
partial-failure-resume-evidenceBulk WorkflowscoveredA partial failure must not leave the next run guessing what already happened.
do-not-promote-one-off-scriptsRepo HygienecoveredDo not promote old one-off scripts into CLI commands.
do-not-depend-on-generated-artifactsRepo HygienecoveredDo not depend on ignored generated artifacts as current source.
external-billing-evidence-historicalRepo HygienecoveredEvidence from a previous billing system is historical unless a task explicitly asks for legacy migration context.

Agent notes

  • Prefer --json when scripting parsers; use --markdown when loading context into an agent.
  • Never treat HTML as the source of truth, regenerate from metro docs <ref> --markdown.
  • Live reads/writes still require tenant flags + confirmation tokens.

On this page