{"openapi":"3.1.0","info":{"title":"Graunt API","version":"0.1.0","description":"Graunt is a marketplace for agent-ready data: evaluated packet assets (datasets and text bundles) for agents, builders, and machine buyers. Listings expose stable IDs, declared rights, provenance metadata, packet checks, pricing, acquisition requirements, and manifest references where available. There is no public composite quality score, quality filter, or quality sort. This document covers only endpoints that exist at runtime today. Roadmap surfaces (machine-native access, pools, demand signals, broader signing-key management) are feature-flagged off and are intentionally omitted. Money values are integer cents. Stripe is the current payment processor. Current marketplace pricing metadata is published at /v1/meta/pricing. U.S. only in the current build. Graunt does not provide legal, financial, medical, or tax advice; buyers are responsible for verifying that any asset is appropriate for their intended use."},"servers":[{"url":"https://api.graunt.com","description":"Machine host"}],"tags":[{"name":"Public discovery","description":"Unauthenticated read endpoints — health/ready/pricing, listing search and detail, public signing-key registry, signed manifest fetch."},{"name":"Authenticated retrieval","description":"Authenticated reads of caller-owned resources — buyer entitlement download, seller's own datasets."},{"name":"Authenticated purchase","description":"Buyer-initiated purchase flow. Current paid purchase execution runs through authenticated buyer-organization accounts; unauthenticated agent paid checkout is not part of the current public surface. Graunt is designed toward delegated agent purchasing under buyer-defined credentials, permissions, spend controls, approval policies, and audit records."},{"name":"Seller","description":"Seller persona — registration, login, dataset upload, listing CRUD, payouts, Stripe Connect onboarding, signing-key management, and the seller listings inventory."},{"name":"Meta","description":"Reserved tag for future meta operations beyond the public-discovery health/ready/pricing trio."},{"name":"Admin","description":"Reserved tag for future admin operations. Admin routes are not exposed in the public OpenAPI surface today (see FORBIDDEN_PATH_PREFIXES)."}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"JWT issued by POST /v1/auth/login or POST /v1/auth/register. Pass as `Authorization: Bearer <token>`."}},"schemas":{"Error":{"type":"object","required":["ok","error"],"properties":{"ok":{"const":false},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable machine-readable error code (e.g. VALIDATION_ERROR, NOT_FOUND, FORBIDDEN)."},"message":{"type":"string"},"details":{"type":"object","additionalProperties":true}}}}},"HealthCheck":{"type":"object","required":["ok","timestamp","schema_version","uptime_seconds","checks"],"properties":{"ok":{"type":"boolean","description":"True when all required dependencies are healthy. HTTP status is always 200 so external uptime monitors can body-match."},"timestamp":{"type":"string","format":"date-time"},"schema_version":{"type":"string"},"uptime_seconds":{"type":"integer","minimum":0},"checks":{"type":"object","additionalProperties":true,"description":"Per-dependency status (postgres, redis, queue, memory)."}}},"Readiness":{"type":"object","required":["ready","timestamp"],"properties":{"ready":{"type":"boolean"},"timestamp":{"type":"string","format":"date-time"},"database":{"type":"string","enum":["ok","error"]},"redis":{"type":"string","enum":["ok","error"]}}},"PricingInfo":{"type":"object","description":"Platform fee + buyer fee schedule. Values are integer cents unless noted."},"ListingSummary":{"type":"object","required":["id","dataset_name","category","price_cents","tags"],"properties":{"id":{"type":"string","format":"uuid"},"dataset_name":{"type":"string"},"category":{"type":"string"},"asset_class":{"type":"string","enum":["DATASET","TEXT_ASSET"]},"file_format":{"type":"string"},"price_cents":{"type":"integer","minimum":0,"description":"Listing price in USD cents. Use 0 for a free listing or at least the marketplace paid-order minimum (50) for a paid listing."},"currency":{"type":"string","enum":["usd"]},"is_free":{"type":"boolean","description":"True when price_cents = 0 (free listing)."},"acquisition_mode":{"type":"string","enum":["PAID_ENTITLED","AUTHENTICATED_FREE_ENTITLED","PUBLIC_TOKEN_GRANT_FREE"],"description":"How the listing is acquired. PAID_ENTITLED: Stripe paid checkout via authenticated buyer org. AUTHENTICATED_FREE_ENTITLED: free acquisition by an authenticated buyer org through POST /v1/purchases (no Stripe call). PUBLIC_TOKEN_GRANT_FREE: anonymous rate-limited grant minting via POST /v1/listings/:id/access-grants."},"payment_required":{"type":"boolean"},"registration_required":{"type":"boolean"},"tags":{"type":"array","items":{"type":"string"}},"created_at":{"type":"string","format":"date-time"}}},"ListingDetail":{"allOf":[{"$ref":"#/components/schemas/ListingSummary"},{"type":"object","properties":{"dataset_description":{"type":"string"},"dataset_row_count":{"type":["integer","null"],"minimum":0},"intended_uses":{"type":"array","items":{"type":"string"}},"rights_attestation":{"type":"boolean"},"provenance":{"type":"object","properties":{"publication_date":{"type":["string","null"],"format":"date"},"version_identifier":{"type":["string","null"]},"source_url":{"type":["string","null"],"format":"uri"},"fetched_at":{"type":["string","null"],"format":"date-time"},"citation_template":{"type":["string","null"]}}},"packet_checks":{"type":"object","description":"Bounded presence-and-fact summary of the listing: declared rights, license family and obligations, provenance recording, manifest references, validation status, content metadata. No composite score, no per-dimension scores, no rank input."},"evaluation_summary":{"type":"object","description":"Narrative companion to packet_checks. Statement makes explicit that there is no universal score and no fitness-for-purpose guarantee."},"download_requires_account_entitlement":{"type":"boolean","description":"True for PAID_ENTITLED and AUTHENTICATED_FREE_ENTITLED listings; download flows through GET /v1/entitlements/:id/download."},"download_requires_access_grant":{"type":"boolean","description":"True for PUBLIC_TOKEN_GRANT_FREE listings; download flows through GET /v1/listings/:id/free-download with a grant token."},"public_free_access":{"type":["object","null"],"description":"Present (non-null) only when acquisition_mode = PUBLIC_TOKEN_GRANT_FREE. Carries grant + download endpoints, grant TTL, rate-limit caps, and a rights/terms notice.","properties":{"enabled":{"const":true},"grant_endpoint":{"type":"string"},"download_endpoint":{"type":"string"},"grant_ttl_seconds":{"type":"integer","minimum":60,"maximum":3600},"rate_limit":{"type":"object","properties":{"per_ip_per_window":{"type":"integer","minimum":1},"window_seconds":{"type":"integer","minimum":60},"per_ip_per_day":{"type":"integer","minimum":1},"global_per_day":{"type":"integer","minimum":1}}},"terms_notice":{"type":"string"}}},"delivery_kind":{"type":"string","enum":["SINGLE_FILE","PACKET_BUNDLE"],"description":"Single-file dataset vs frozen packet bundle. Both delivery kinds are publicly visible on the catalog. SINGLE_FILE delivers via GET /v1/entitlements/{id}/download; PACKET_BUNDLE delivers via GET /v1/entitlements/{id}/packet-bundle (manifest + per-asset presigned URLs). Public listing detail returns the bundle aggregate (asset_count, manifest_sha256, total_bytes) without per-asset details — those return through the entitlement after acquisition."},"packet_bundle":{"type":["object","null"],"description":"Bundle aggregate (bundle_id, revision_id, revision_number, manifest_sha256, asset_count, total_bytes, frozen_at) when delivery_kind=PACKET_BUNDLE; null when SINGLE_FILE."},"commercial_terms":{"$ref":"#/components/schemas/CommercialTerms","description":"Bounded, agent-readable commercial-terms aggregate. Same shape is persisted as an immutable purchase-time snapshot at purchase creation (see InitiatePurchaseResponse). Forbidden public fields: platform fee, seller net, payout split, allocation rows, raw payment-processor objects, presigned URLs, PII."}}}]},"CommercialTerms":{"type":"object","description":"Bounded, agent-readable commercial-terms aggregate. Built deterministically from existing listing fields. Same shape is the strict-validated snapshot persisted at purchase creation; never rebuilt thereafter.","required":["schema_version","listing_id","listing_status","listing_updated_at_utc","pricing","acquisition","delivery","packet","rights","publication","checkout"],"properties":{"schema_version":{"const":1},"listing_id":{"type":"string","format":"uuid"},"listing_status":{"type":"string"},"listing_updated_at_utc":{"type":"string","format":"date-time"},"pricing":{"type":"object","required":["price_cents","currency","is_free","paid_order_minimum_cents","buyer_total_cents_full_acquisition"],"properties":{"price_cents":{"type":"integer","minimum":0},"currency":{"const":"usd"},"is_free":{"type":"boolean"},"paid_order_minimum_cents":{"type":"integer","minimum":0},"buyer_total_cents_full_acquisition":{"type":["integer","null"],"minimum":0,"description":"Computable buyer-total when the listing is paid (gross + processing + delivery); null when free."}}},"acquisition":{"type":"object","required":["acquisition_mode","payment_required","registration_required","download_requires_account_entitlement","download_requires_access_grant"],"properties":{"acquisition_mode":{"type":"string","enum":["PAID_ENTITLED","AUTHENTICATED_FREE_ENTITLED","PUBLIC_TOKEN_GRANT_FREE","PRIVATE_GRANT"]},"payment_required":{"type":"boolean"},"registration_required":{"type":"boolean"},"download_requires_account_entitlement":{"type":"boolean"},"download_requires_access_grant":{"type":"boolean"}}},"delivery":{"type":"object","required":["delivery_kind","packet_bundle"],"properties":{"delivery_kind":{"type":"string","enum":["SINGLE_FILE","PACKET_BUNDLE"]},"packet_bundle":{"type":["object","null"],"description":"Required (non-null) iff delivery_kind=PACKET_BUNDLE. Bounded summary — never per-asset object key, original filename, or asset role.","properties":{"revision_id":{"type":"string","format":"uuid"},"revision_number":{"type":"integer","minimum":1},"manifest_sha256":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"},"asset_count":{"type":"integer","minimum":1},"total_bytes":{"type":"integer","minimum":0},"frozen_at":{"type":["string","null"],"format":"date-time"}}}}},"packet":{"type":"object","required":["packet_family","packet_kind","packet_manifest_present","manifest_sha256","manifest_signed"],"properties":{"packet_family":{"type":["string","null"]},"packet_kind":{"type":["string","null"]},"packet_manifest_present":{"type":"boolean"},"manifest_sha256":{"type":["string","null"],"pattern":"^sha256:[a-f0-9]{64}$"},"manifest_signed":{"type":"boolean"}}},"rights":{"type":"object","required":["license_family","citation_required","training_allowed","redistribution_allowed","contains_personal_data","update_pattern","access_mode","delivery_mode","transferability","agent_access_allowed"],"properties":{"license_family":{"type":"string"},"citation_required":{"type":"boolean"},"training_allowed":{"type":"boolean"},"redistribution_allowed":{"type":"boolean"},"contains_personal_data":{"type":"string","enum":["NO","ANONYMIZED","YES"]},"update_pattern":{"type":"string"},"access_mode":{"type":"string"},"delivery_mode":{"type":"string"},"transferability":{"const":"NONE"},"agent_access_allowed":{"type":"boolean"}}},"publication":{"type":"object","required":["publication_status","publisher_role","language","has_doi"],"properties":{"publication_status":{"type":["string","null"]},"publisher_role":{"type":["string","null"]},"language":{"type":["string","null"]},"has_doi":{"type":"boolean"}}},"checkout":{"type":"object","required":["current_channel","agent_checkout_available"],"properties":{"current_channel":{"const":"STRIPE_PAYMENT_INTENT","description":"Byte-identical to the durable internal payment-channel column at v0. Names the Stripe primitive used (`automatic_payment_methods.enabled = true` routes cards + Apple Pay + Google Pay + Stripe Link uniformly under one PaymentIntent). Carries no implication of live Shared Payment Token support, agent checkout, or autonomous purchase — `agent_checkout_available` is the explicit machine-readable boolean for that."},"agent_checkout_available":{"const":false,"description":"Explicit machine-readable signal that no autonomous agent checkout is live at v0. Future operational expansion may flip this under a new locked decision."}}}}},"ListListingsResponse":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"type":"object","required":["listings","pagination"],"properties":{"listings":{"type":"array","items":{"$ref":"#/components/schemas/ListingSummary"}},"pagination":{"type":"object","required":["page","limit","total"],"properties":{"page":{"type":"integer","minimum":1},"limit":{"type":"integer","minimum":1,"maximum":100},"total":{"type":"integer","minimum":0}}}}}}},"ListingDetailResponse":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"$ref":"#/components/schemas/ListingDetail"}}},"RegisterRequest":{"type":"object","required":["name","email","password","type"],"properties":{"name":{"type":"string","minLength":1,"maxLength":100},"email":{"type":"string","format":"email"},"password":{"type":"string","minLength":12},"type":{"type":"string","enum":["BUYER","SELLER","BOTH"]}}},"LoginRequest":{"type":"object","required":["email","password"],"properties":{"email":{"type":"string","format":"email"},"password":{"type":"string"}}},"AuthResponse":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"type":"object","required":["token","org_id"],"properties":{"token":{"type":"string","description":"JWT bearer token to use in subsequent requests."},"org_id":{"type":"string","format":"uuid"}}}}},"InitiatePurchaseRequest":{"type":"object","required":["listing_id","idempotency_key"],"properties":{"listing_id":{"type":"string","format":"uuid"},"idempotency_key":{"type":"string","minLength":8,"description":"Caller-supplied key to deduplicate retries of the same intent."},"entitlement_scope":{"type":"string","enum":["FULL"],"description":"Only FULL is supported at alpha."}}},"InitiatePurchaseResponse":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"type":"object","required":["purchase_id","status"],"properties":{"purchase_id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["PENDING_PAYMENT","COMPLETED"]},"stripe_client_secret":{"type":["string","null"],"description":"Stripe PaymentIntent client secret. Absent when the purchase completed synchronously."},"gross_amount_cents":{"type":"integer"},"processing_fee_cents":{"type":"integer"},"delivery_fee_cents":{"type":"integer"},"buyer_total_cents":{"type":"integer"},"commercial_terms_snapshot":{"$ref":"#/components/schemas/CommercialTerms","description":"Immutable purchase-time snapshot of the listing's commercial terms. Captured atomically with the purchase row insert (paid and free paths); never mutated by webhook completion, confirm replay, refund, or idempotency replay. Idempotency replay returns the original snapshot, not a rebuilt one."}}}}},"DownloadResponse":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"type":"object","required":["download_url","expires_in_seconds","downloads_remaining"],"properties":{"download_url":{"type":"string","format":"uri","description":"Presigned URL. TTL is <= 15 minutes per platform rule; the current value is 600 seconds."},"expires_in_seconds":{"type":"integer","minimum":1,"maximum":900},"downloads_remaining":{"type":"integer","minimum":0},"content_sha256":{"type":["string","null"],"description":"SHA-256 of the asset file, lowercase hex."},"file_size_bytes":{"type":["integer","null"],"minimum":0}}}}},"PacketBundleAssetDelivery":{"type":"object","description":"Per-asset bundle delivery row. download_url is a short-lived presigned URL — never log, never persist.","required":["asset_id","ordering","asset_role","file_format","file_size_bytes","content_sha256","original_filename","download_url","expires_at"],"properties":{"asset_id":{"type":"string","format":"uuid"},"ordering":{"type":"integer","minimum":0,"maximum":255},"asset_role":{"type":"string","enum":["PRIMARY","SUPPORTING","EVIDENCE","MANIFEST","LEGAL_NOTICE"]},"file_format":{"type":"string"},"file_size_bytes":{"type":"integer","minimum":0},"content_sha256":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"},"original_filename":{"type":"string","minLength":1,"maxLength":255},"download_url":{"type":"string","format":"uri","description":"Short-lived presigned URL (TTL 600 seconds). Sensitive — must not be logged, audited, or persisted."},"expires_at":{"type":"string","format":"date-time","description":"Shared across every asset_role in one response."}}},"EntitlementPacketBundleResponse":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"type":"object","required":["entitlement_id","listing_id","delivery_kind","packet_bundle_revision_id","bundle_id","revision_number","manifest_sha256","total_bytes","asset_count","expires_at","downloads_remaining","assets"],"properties":{"entitlement_id":{"type":"string","format":"uuid"},"listing_id":{"type":"string","format":"uuid"},"delivery_kind":{"type":"string","const":"PACKET_BUNDLE"},"packet_bundle_revision_id":{"type":"string","format":"uuid"},"bundle_id":{"type":"string","format":"uuid"},"revision_number":{"type":"integer","minimum":1},"manifest_sha256":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"},"total_bytes":{"type":"integer","minimum":0},"asset_count":{"type":"integer","minimum":1},"expires_at":{"type":"string","format":"date-time"},"downloads_remaining":{"type":"integer","minimum":0},"assets":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/PacketBundleAssetDelivery"}}}}}},"UploadDatasetResponse":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"type":"object","required":["dataset_id","status"],"properties":{"dataset_id":{"type":"string","format":"uuid"},"status":{"type":"string","description":"Dataset lifecycle state (e.g. PENDING_QC, PASSED, FAILED)."}}}}},"ListDatasetsResponse":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"type":"object","required":["datasets"],"properties":{"datasets":{"type":"array","items":{"type":"object"}},"pagination":{"type":"object"}}}}},"CreateListingRequest":{"type":"object","required":["price_cents"],"properties":{"dataset_id":{"type":"string","format":"uuid","description":"Single-file dataset delivery target. Mutually exclusive with packet_bundle_revision_id. Provide exactly one delivery target."},"packet_bundle_revision_id":{"type":"string","format":"uuid","description":"Packet bundle revision delivery target — must reference a finalized revision in the caller's org. Mutually exclusive with dataset_id. Provide exactly one delivery target. Bundle-backed listings transition to ACTIVE through admin review and deliver via GET /v1/entitlements/{id}/packet-bundle."},"price_cents":{"type":"integer","minimum":0,"description":"Listing price in USD cents. Use 0 for a free listing or at least the marketplace paid-order minimum (50) for a paid listing. Values 1..49 are rejected."},"tags":{"type":"array","items":{"type":"string"}},"usage_restrictions":{"type":"array","items":{"type":"string"}}},"description":"Provide exactly one of dataset_id or packet_bundle_revision_id. Packet manifest fields (packet_kind, packet_manifest, version_identifier) remain optional and orthogonal to the delivery target."},"CreateListingResponse":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"type":"object","required":["listing_id","status"],"properties":{"listing_id":{"type":"string","format":"uuid"},"status":{"type":"string","description":"Listing lifecycle state — new listings enter PENDING_REVIEW."}}}}},"UpdateListingRequest":{"type":"object","description":"Partial update. Sellers may adjust price (0 for free, or at least the marketplace paid-order minimum), tags, usage_restrictions, content_kind, and rights_block.","properties":{"price_cents":{"type":"integer","minimum":0,"description":"Listing price in USD cents. Use 0 for a free listing or at least the marketplace paid-order minimum (50) for a paid listing."},"tags":{"type":"array","items":{"type":"string"}},"usage_restrictions":{"type":"array","items":{"type":"string"}},"content_kind":{"type":"string"},"rights_block":{"type":"object"}}},"UpdateListingResponse":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"$ref":"#/components/schemas/ListingDetail"}}},"StripeConnectResponse":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"type":"object","required":["onboarding_url"],"properties":{"onboarding_url":{"type":"string","format":"uri","description":"Stripe-hosted URL that completes seller onboarding. Expires within one hour."}}}}},"ListPayoutsResponse":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"type":"object","required":["payouts","pagination"],"properties":{"payouts":{"type":"array","items":{"type":"object"}},"pagination":{"type":"object"}}}}},"SellerListingsItem":{"type":"object","description":"Org-scoped listing inventory row returned by GET /v1/seller/listings. Denormalized — no join required.","required":["id","dataset_name","status","packet_kind","packet_family","price_cents","created_at","updated_at","validation_status","delivery_kind","packet_bundle_revision_id"],"properties":{"id":{"type":"string","format":"uuid"},"dataset_name":{"type":"string"},"status":{"type":"string","enum":["PENDING_REVIEW","ACTIVE","PAUSED","ARCHIVED","REJECTED","SUSPENDED","NEEDS_REFINEMENT"]},"packet_kind":{"type":["string","null"]},"packet_family":{"type":["string","null"]},"price_cents":{"type":"integer","minimum":0,"description":"Listing price in USD cents. 0 for free, otherwise at least the marketplace paid-order minimum (50)."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"validation_status":{"type":["string","null"]},"delivery_kind":{"type":"string","enum":["SINGLE_FILE","PACKET_BUNDLE"],"description":"SINGLE_FILE for dataset-backed listings; PACKET_BUNDLE for bundle-backed listings. Both delivery kinds are publicly visible on the catalog and deliver through the entitlement routes after acquisition."},"packet_bundle_revision_id":{"type":["string","null"],"format":"uuid","description":"Frozen packet_bundle_revision id when delivery_kind=PACKET_BUNDLE; null otherwise."}}},"SellerPacketBundleListItem":{"type":"object","description":"Seller-owned packet bundle row returned by GET /v1/seller/packet-bundles. latest_revision is null when no revision has been finalized yet (only emitted when finalized=false).","required":["bundle_id","name","description","archived_at","created_at","latest_revision"],"properties":{"bundle_id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":"string"},"archived_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"},"latest_revision":{"type":["object","null"],"required":["revision_id","revision_number","manifest_sha256","total_bytes","asset_count","frozen_at"],"properties":{"revision_id":{"type":"string","format":"uuid"},"revision_number":{"type":"integer","minimum":1},"manifest_sha256":{"type":"string"},"total_bytes":{"type":"integer","minimum":0},"asset_count":{"type":"integer","minimum":1},"frozen_at":{"type":"string","format":"date-time"}}}}},"ListSellerPacketBundlesResponse":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"type":"object","required":["items","page","per_page"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/SellerPacketBundleListItem"}},"page":{"type":"integer","minimum":1},"per_page":{"type":"integer","minimum":1,"maximum":100}}}}},"ListSellerListingsResponse":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"type":"object","required":["items","total","page","per_page"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/SellerListingsItem"}},"total":{"type":"integer","minimum":0},"page":{"type":"integer","minimum":1},"per_page":{"type":"integer","minimum":1,"maximum":100}}}}},"Finding":{"type":"object","required":["check_type","field","message","blocks_publish"],"properties":{"check_type":{"type":"string","enum":["presence","validation","coherence","rights_block","integrity_basis"]},"field":{"type":"string"},"message":{"type":"string"},"blocks_publish":{"type":"boolean"}}},"LastAdminReview":{"type":"object","required":["kind","occurred_at","seller_safe_summary"],"properties":{"kind":{"type":"string","enum":["rejected","needs_refinement","publish_blocked","approved","published"]},"occurred_at":{"type":"string","format":"date-time"},"seller_safe_summary":{"type":"string"},"decision_note":{"type":"string","description":"Admin-authored note. Present for kind=rejected and kind=needs_refinement only. Server-side capped at 2000 chars; UI escapes."},"blocking_check_types":{"type":"array","items":{"type":"string"},"description":"Present for kind=publish_blocked only."},"findings_count":{"type":"integer","minimum":0,"description":"Present for kind=publish_blocked only."},"reason_code":{"type":"string","enum":["RIGHTS_INSUFFICIENT","PROVENANCE_INSUFFICIENT","KNOWN_LIMITATIONS_MISSING","MANIFEST_INVALID","BUNDLE_VALIDATION_FAILED","FRESHNESS_CLAIM_UNSUPPORTED","CATEGORY_PROHIBITED","CATEGORY_LABEL_NOT_MEANINGFUL","RIGHTS_BLOCK_INCOHERENT","RIGHTS_PASSPORT_INCOHERENT","PUBLICATION_METADATA_MISSING_REQUIRED","SCANNER_SIGNAL_REQUIRES_MANUAL_REVIEW","OTHER"],"description":"Canonical reject / remediation reason code. Present for kind=rejected and kind=needs_refinement only when the audit row carries a canonical value. Earlier audit rows may omit this field."},"remediation_text":{"type":"string","description":"Deterministic seller-visible remediation text mapped from reason_code. Bounded language. Present iff reason_code is present and canonical."}}},"SellerListingDetail":{"type":"object","required":["id","status","dataset_name","delivery_kind","available_actions","payout_summary","validation_findings","last_admin_review"],"properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["PENDING_REVIEW","ACTIVE","PAUSED","ARCHIVED","REJECTED","SUSPENDED","NEEDS_REFINEMENT"]},"dataset_name":{"type":"string"},"dataset_description":{"type":"string"},"dataset_category":{"type":"string"},"dataset_row_count":{"type":["integer","null"]},"price_cents":{"type":"integer","minimum":0},"tags":{"type":"array","items":{"type":"string"}},"usage_restrictions":{"type":"array","items":{"type":"string"}},"content_kind":{"type":"string"},"packet_kind":{"type":["string","null"]},"packet_family":{"type":["string","null"]},"packet_manifest":{},"version_identifier":{"type":["string","null"]},"validation_status":{"type":["string","null"]},"packet_validation_report":{},"packet_manifest_hash":{"type":["string","null"]},"packet_merkle_root":{"type":["string","null"]},"signed_at":{"type":["string","null"],"format":"date-time"},"signer_key_id":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"delivery_kind":{"type":"string","enum":["SINGLE_FILE","PACKET_BUNDLE"]},"packet_bundle":{"type":["object","null"]},"payout_summary":{"type":"object"},"available_actions":{"type":"object","required":["can_edit","can_pause","can_unpause","can_archive","can_resubmit_for_review"],"properties":{"can_edit":{"type":"boolean"},"can_pause":{"type":"boolean"},"can_unpause":{"type":"boolean"},"can_archive":{"type":"boolean"},"can_resubmit_for_review":{"type":"boolean"}}},"validation_findings":{"oneOf":[{"type":"null"},{"type":"array","items":{"$ref":"#/components/schemas/Finding"}}]},"last_admin_review":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/LastAdminReview"}]}}},"GetSellerListingDetailResponse":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"$ref":"#/components/schemas/SellerListingDetail"}}},"SellerListingPacketBundleAsset":{"type":"object","required":["id","ordering","asset_role","original_filename","file_format","file_size_bytes","content_sha256"],"properties":{"id":{"type":"string","format":"uuid"},"ordering":{"type":"integer","minimum":0},"asset_role":{"type":"string"},"original_filename":{"type":"string"},"file_format":{"type":"string"},"file_size_bytes":{"type":"integer","minimum":0},"content_sha256":{"type":"string"}}},"SellerListingPacketBundleAssetGroup":{"type":"object","required":["logical_asset_id","label","role","formats","asset_count","asset_orderings","total_bytes"],"properties":{"logical_asset_id":{"type":"string"},"label":{"type":"string"},"role":{"type":"string"},"formats":{"type":"array","items":{"type":"string"}},"asset_count":{"type":"integer","minimum":0},"asset_orderings":{"type":"array","items":{"type":"integer","minimum":0}},"total_bytes":{"type":"integer","minimum":0}}},"SellerListingPacketBundle":{"type":"object","required":["listing_id","bundle","assets","asset_groups"],"properties":{"listing_id":{"type":"string","format":"uuid"},"bundle":{"type":"object","required":["bundle_id","name","revision_id","revision_number","manifest_sha256","asset_count","total_bytes","frozen_at","physical_asset_count","logical_asset_count","format_variant_count"],"properties":{"bundle_id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":["string","null"]},"archived_at":{"type":["string","null"],"format":"date-time"},"revision_id":{"type":"string","format":"uuid"},"revision_number":{"type":"integer","minimum":1},"manifest_sha256":{"type":"string"},"asset_count":{"type":"integer","minimum":0},"total_bytes":{"type":"integer","minimum":0},"frozen_at":{"type":"string","format":"date-time"},"physical_asset_count":{"type":"integer","minimum":0},"logical_asset_count":{"type":"integer","minimum":0},"format_variant_count":{"type":"integer","minimum":0}}},"assets":{"type":"array","items":{"$ref":"#/components/schemas/SellerListingPacketBundleAsset"}},"asset_groups":{"type":"array","items":{"$ref":"#/components/schemas/SellerListingPacketBundleAssetGroup"}}}},"GetSellerListingPacketBundleResponse":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"$ref":"#/components/schemas/SellerListingPacketBundle"}}},"ManifestDryRunResult":{"type":"object","required":["findings","would_block_publish","manifest_summary"],"properties":{"findings":{"type":"array","items":{"$ref":"#/components/schemas/Finding"}},"would_block_publish":{"type":"boolean"},"manifest_summary":{"oneOf":[{"type":"null"},{"type":"object","required":["packet_kind","packet_family","version_identifier"],"properties":{"packet_kind":{"type":["string","null"]},"packet_family":{"type":["string","null"]},"version_identifier":{"type":["string","null"]}}}]}}},"ValidateListingManifestDryRunResponse":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"$ref":"#/components/schemas/ManifestDryRunResult"}}},"MetaSellerStandardsData":{"type":"object","required":["schema_version","requirement_set_version","standards_url","endpoint_url","trust_posture","packet_families","packet_kinds","validation_statuses","accepted_formats","source_types","bundle","rights_vocabulary","rights_passport_vocabulary","publication_vocabulary","requirement_groups","submission_checklist","review"],"properties":{"schema_version":{"type":"integer","enum":[1]},"requirement_set_version":{"type":"integer","enum":[1]},"standards_url":{"type":"string","enum":["/sellers/standards"]},"endpoint_url":{"type":"string","enum":["/v1/meta/seller-standards"]},"trust_posture":{"type":"object","required":["evaluated_not_verified","seller_responsibility_for_rights_and_provenance","objective_validation_scope"],"properties":{"evaluated_not_verified":{"const":true},"seller_responsibility_for_rights_and_provenance":{"const":true},"objective_validation_scope":{"type":"array","items":{"type":"string"}}}},"packet_families":{"type":"array","items":{"type":"object","required":["id","human_label","summary"],"properties":{"id":{"type":"string"},"human_label":{"type":"string"},"summary":{"type":"string"}}}},"packet_kinds":{"type":"array","items":{"type":"object","required":["id","family","human_label","description"],"properties":{"id":{"type":"string"},"family":{"type":"string"},"human_label":{"type":"string"},"description":{"type":"string"}}}},"validation_statuses":{"type":"array","items":{"type":"object","required":["id","human_label","interpretation","terminal"],"properties":{"id":{"type":"string","enum":["DRAFT","STRUCTURAL_VALID","EVIDENCE_INCOMPLETE","PASSED_WITH_NOTES","PASSED","PUBLISH_BLOCKED"]},"human_label":{"type":"string"},"interpretation":{"type":"string"},"terminal":{"type":"boolean"}}}},"accepted_formats":{"description":"Manifest delivery_format vocabulary — what `packet_manifest.delivery_format` accepts. Distinct from `bundle.accepted_asset_formats`, which is the narrower per-asset upload set.","type":"array","items":{"type":"object","required":["id","human_label","extension","mime_type","scope"],"properties":{"id":{"type":"string"},"human_label":{"type":"string"},"extension":{"type":["string","null"]},"mime_type":{"type":["string","null"]},"scope":{"type":"string","enum":["manifest_delivery_format"]}}}},"source_types":{"type":"array","items":{"type":"string"}},"bundle":{"type":"object","required":["max_assets","max_asset_bytes","max_total_bytes","asset_roles","required_asset_metadata","accepted_asset_formats"],"properties":{"max_assets":{"type":"integer","minimum":1},"max_asset_bytes":{"type":"integer","minimum":1},"max_total_bytes":{"type":"integer","minimum":1},"asset_roles":{"type":"array","items":{"type":"object","required":["id","human_label","description"],"properties":{"id":{"type":"string","enum":["PRIMARY","SUPPORTING","EVIDENCE","MANIFEST","LEGAL_NOTICE"]},"human_label":{"type":"string"},"description":{"type":"string"}}}},"required_asset_metadata":{"type":"array","items":{"type":"string"}},"accepted_asset_formats":{"description":"Per-asset upload format vocabulary accepted by the bundle validator (`packet_bundle_asset.file_format`). Narrower than the manifest delivery_format set surfaced in `accepted_formats`.","type":"array","items":{"type":"string","enum":["CSV","JSON","PARQUET","TEXT","JSONL","PDF"]}}}},"rights_vocabulary":{"type":"object","required":["license_families","rights_origins","update_patterns","personal_data_levels","duration_classes"],"properties":{"license_families":{"type":"array","items":{"type":"string"}},"rights_origins":{"type":"array","items":{"type":"string"}},"update_patterns":{"type":"array","items":{"type":"string"}},"personal_data_levels":{"type":"array","items":{"type":"string"}},"duration_classes":{"type":"array","items":{"type":"string"}}}},"rights_passport_vocabulary":{"type":"object","required":["access_modes","delivery_modes","actions"],"properties":{"access_modes":{"type":"array","items":{"type":"string"}},"delivery_modes":{"type":"array","items":{"type":"string"}},"actions":{"type":"array","items":{"type":"string"}}}},"publication_vocabulary":{"type":"object","required":["publisher_roles","publication_statuses","standard_identifier_kinds"],"properties":{"publisher_roles":{"type":"array","items":{"type":"string"}},"publication_statuses":{"type":"array","items":{"type":"string"}},"standard_identifier_kinds":{"type":"array","items":{"type":"string"}}}},"requirement_groups":{"type":"array","items":{"type":"object","required":["id","title","anchor","summary","requirements"],"properties":{"id":{"type":"string","enum":["rights_and_provenance","publication_metadata","freshness_and_limitations","manifests_and_integrity","packet_bundles_and_assets","accepted_formats_group","evaluated_quality","agent_submission_expectations"]},"title":{"type":"string"},"anchor":{"type":"string"},"summary":{"type":"string"},"requirements":{"type":"array","items":{"type":"object","required":["id","severity","applies_to","summary","expected_evidence","machine_fields"],"properties":{"id":{"type":"string"},"severity":{"type":"string","enum":["required","recommended","conditional","prohibited"]},"applies_to":{"type":"array","items":{"type":"string","enum":["all_packets","datasets","text_assets","bundles","manifests","freshness_sensitive","seller_rights_claims","agent_prepared"]}},"summary":{"type":"string"},"expected_evidence":{"type":"array","items":{"type":"string"}},"machine_fields":{"type":"array","items":{"type":"string"}},"not_a_guarantee":{"type":"string"}}}}}}},"submission_checklist":{"type":"object","required":["minimum_for_review","stronger_packet_signals","prohibited_or_high_risk_claims"],"properties":{"minimum_for_review":{"type":"array","items":{"type":"string"}},"stronger_packet_signals":{"type":"array","items":{"type":"string"}},"prohibited_or_high_risk_claims":{"type":"array","items":{"type":"string"}}}},"review":{"type":"object","required":["evaluated_not_verified","accepted_states","blocking_states","remediation_expectations"],"properties":{"evaluated_not_verified":{"const":true},"accepted_states":{"type":"array","items":{"type":"string","enum":["DRAFT","STRUCTURAL_VALID","EVIDENCE_INCOMPLETE","PASSED_WITH_NOTES","PASSED","PUBLISH_BLOCKED"]}},"blocking_states":{"type":"array","items":{"type":"string","enum":["DRAFT","STRUCTURAL_VALID","EVIDENCE_INCOMPLETE","PASSED_WITH_NOTES","PASSED","PUBLISH_BLOCKED"]}},"remediation_expectations":{"type":"array","items":{"type":"string"}}}}}},"MetaSellerStandardsResponse":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"$ref":"#/components/schemas/MetaSellerStandardsData"}}},"MetaAgentSurfaceData":{"type":"object","required":["schema_version","brand_line","positioning","current_human_surfaces","current_machine_surfaces","trust_primitives","scanner_signals","participation","search_and_discovery","roadmap_direction","posture_notes"],"properties":{"schema_version":{"type":"integer","enum":[1]},"brand_line":{"type":"string"},"positioning":{"type":"string"},"current_human_surfaces":{"type":"object"},"current_machine_surfaces":{"type":"object"},"trust_primitives":{"type":"object"},"scanner_signals":{"type":"object","required":["ceiling","non_blocking","non_certification","non_ranking_input","non_payout_input","non_eligibility_input","descriptors"],"properties":{"ceiling":{"type":"string","enum":["DISCLOSE_ONLY"]},"non_blocking":{"const":true},"non_certification":{"const":true},"non_ranking_input":{"const":true},"non_payout_input":{"const":true},"non_eligibility_input":{"const":true},"descriptors":{"type":"array","items":{"type":"object","required":["kind","applies_to","description","posture"],"properties":{"kind":{"type":"string"},"applies_to":{"type":"string"},"description":{"type":"string"},"posture":{"type":"string","enum":["DISCLOSE_ONLY"]}}}}}},"participation":{"type":"object"},"search_and_discovery":{"type":"object"},"roadmap_direction":{"type":"object"},"posture_notes":{"type":"object"}}},"MetaAgentSurfaceResponse":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"$ref":"#/components/schemas/MetaAgentSurfaceData"}}},"MetaAgentParticipationData":{"type":"object","required":["schema_version","positioning","participation","roadmap_direction","posture_notes"],"properties":{"schema_version":{"type":"integer","enum":[1]},"positioning":{"type":"string"},"participation":{"type":"object","required":["summary","seller_payout_path","org_level_beneficiary","allocation_ledger_status","future_role_widening","reward_kinds_available_today","reward_kinds_reserved","future_tradability_in_alpha","compensated_recommendation_disclosure_required","roles","allocation_role_kind_enum","agent_profile_role_kind_enum"],"properties":{"summary":{"type":"string"},"seller_payout_path":{"type":"string"},"org_level_beneficiary":{"const":true},"allocation_ledger_status":{"type":"string","enum":["LIVE_SELLER_AND_PLATFORM"]},"future_role_widening":{"type":"string","enum":["PLANNED"]},"reward_kinds_available_today":{"type":"array","items":{"type":"string"}},"reward_kinds_reserved":{"type":"array","items":{"type":"string"}},"future_tradability_in_alpha":{"const":false},"compensated_recommendation_disclosure_required":{"const":true},"roles":{"type":"array","items":{"type":"object"}},"allocation_role_kind_enum":{"type":"array","items":{"type":"string"}},"agent_profile_role_kind_enum":{"type":"array","items":{"type":"string"}}}},"roadmap_direction":{"type":"object"},"posture_notes":{"type":"object"}}},"MetaAgentParticipationResponse":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"$ref":"#/components/schemas/MetaAgentParticipationData"}}},"MetaScannerSignalsData":{"type":"object","required":["schema_version","ceiling","non_blocking","non_certification","non_ranking_input","non_payout_input","non_eligibility_input","descriptors","forbidden_in_automated_outputs"],"properties":{"schema_version":{"type":"integer","enum":[1]},"ceiling":{"type":"string","enum":["DISCLOSE_ONLY"]},"non_blocking":{"const":true},"non_certification":{"const":true},"non_ranking_input":{"const":true},"non_payout_input":{"const":true},"non_eligibility_input":{"const":true},"descriptors":{"type":"array","items":{"type":"object"}},"forbidden_in_automated_outputs":{"type":"array","items":{"type":"string"}}}},"MetaScannerSignalsResponse":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"$ref":"#/components/schemas/MetaScannerSignalsData"}}},"MetaSearchContractData":{"type":"object","required":["schema_version","search_endpoint","ranking_formula_summary","filters","malformed_value_behavior","unknown_filter_value_behavior","invariants"],"properties":{"schema_version":{"type":"integer","enum":[1]},"search_endpoint":{"type":"string","enum":["/v1/listings"]},"ranking_formula_summary":{"type":"string"},"filters":{"type":"array","items":{"type":"object","required":["param","kind","description","ranking_role"],"properties":{"param":{"type":"string"},"kind":{"type":"string","enum":["literal_string","enum","integer","boolean","list"]},"description":{"type":"string"},"ranking_role":{"type":"string","enum":["HARD_FILTER_ONLY"]}}}},"malformed_value_behavior":{"type":"string"},"unknown_filter_value_behavior":{"type":"string"},"invariants":{"type":"object","required":["no_hidden_ranking_inputs","no_composite_trust_score","no_agent_reputation_multiplier","no_seller_prestige_relevance_boost","no_quality_coefficient"],"properties":{"no_hidden_ranking_inputs":{"const":true},"no_composite_trust_score":{"const":true},"no_agent_reputation_multiplier":{"const":true},"no_seller_prestige_relevance_boost":{"const":true},"no_quality_coefficient":{"const":true}}}}},"MetaSearchContractResponse":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"$ref":"#/components/schemas/MetaSearchContractData"}}}}},"paths":{"/v1/meta/health":{"get":{"operationId":"metaHealth","tags":["Public discovery"],"summary":"Liveness probe — always HTTP 200.","description":"Returns HTTP 200 regardless of dependency state; the JSON body's `ok` flag reflects actual health. External uptime monitors body-match on `\"ok\":true`. Do not use this probe for load-balancer draining — use /v1/meta/ready for that.","security":[],"responses":{"200":{"description":"Liveness envelope. `ok` is a boolean; HTTP status is always 200.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthCheck"}}}}}}},"/v1/meta/ready":{"get":{"operationId":"metaReady","tags":["Public discovery"],"summary":"Readiness probe — HTTP 503 when a required dependency is unreachable.","description":"Returns HTTP 200 with `ready: true` when Postgres and Redis are reachable. Returns HTTP 503 with `ready: false` and a failing dependency name when any required dependency is unhealthy. This is the ALB target-group and ECS container health probe.","security":[],"responses":{"200":{"description":"All required dependencies are healthy.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Readiness"}}}},"503":{"description":"One or more required dependencies are unreachable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Readiness"}}}}}}},"/v1/meta/pricing":{"get":{"operationId":"metaPricing","tags":["Public discovery"],"summary":"Platform pricing schedule.","description":"Returns the 15% commission rate, processing-fee formula, delivery-fee schedule, current marketplace checkout constraints, and a worked example. All monetary values are integer cents.","security":[],"responses":{"200":{"description":"Pricing data envelope.","content":{"application/json":{"schema":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"$ref":"#/components/schemas/PricingInfo"}}}}}}}}},"/v1/meta/seller-standards":{"get":{"operationId":"metaSellerStandards","tags":["Public discovery"],"summary":"Machine-readable seller and agent acceptance standards.","description":"Returns the canonical acceptance-standards contract: packet families, packet kinds, validation statuses, manifest delivery-format vocabulary (`accepted_formats`, scope=`manifest_delivery_format`), per-asset upload-format vocabulary (`bundle.accepted_asset_formats`), bundle limits, rights / publication vocabularies, eight requirement groups with 28 stable requirement IDs, a submission checklist, and the evaluated-not-verified review posture. Public, no auth, no DB. Deterministic: two sequential requests return byte-identical JSON. cache-control: public, max-age=300. Requirement IDs are submission-checklist identifiers, not reject reasons; the canonical reject-reason taxonomy is owned by a separate slice. Schema version + requirement set version are pinned at 1.","security":[],"responses":{"200":{"description":"Acceptance-standards contract envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetaSellerStandardsResponse"}}}}}}},"/v1/meta/agent-surface":{"get":{"operationId":"metaAgentSurface","tags":["Public discovery"],"summary":"Omnibus agent-readable surface contract.","description":"Returns the canonical agent-readable surface contract: brand line + positioning, current human + machine surfaces, trust primitives (rights_block / rights_passport / publication_metadata / packet_manifest / content_sha256 / packet_manifest_hash / signed manifest endpoint / packet_checks / admin review gate), scanner-signal posture (DISCLOSE_ONLY ceiling + bounded language descriptors for every scanner kind), participation contract (live seller + platform allocation, reserved contributor roles, reward kinds available today vs reserved, compensated-recommendation-disclosure requirement, future_tradability_in_alpha=false), search-and-discovery contract (ranking formula summary, filter list, ranking invariants), and roadmap direction. Public, no auth, no DB. Deterministic: two sequential requests return byte-identical JSON. cache-control: public, max-age=300. Schema version pinned at 1.","security":[],"responses":{"200":{"description":"Agent-readable surface contract envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetaAgentSurfaceResponse"}}}}}}},"/v1/meta/agent-participation":{"get":{"operationId":"metaAgentParticipation","tags":["Public discovery"],"summary":"Machine-readable participation contract.","description":"Returns the participation focus of the agent-readable surface contract: allocation-ledger status (LIVE_SELLER_AND_PLATFORM), reserved contributor role kinds (BUILDER / VALIDATOR / CURATOR / REFERRAL / DEMAND_SCOUT / RECRUITER / UPDATE_MAINTAINER / BUYER_CREDIT) with substrate status, reward kinds available today (CASH, ATTRIBUTION_ONLY) vs reserved (GRAUNT_CREDIT, REPUTATION_POINT), future_tradability_in_alpha=false, compensated_recommendation_disclosure_required=true, and the roadmap-direction block. Public, no auth, no DB. Deterministic. cache-control: public, max-age=300.","security":[],"responses":{"200":{"description":"Participation contract envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetaAgentParticipationResponse"}}}}}}},"/v1/meta/scanner-signals":{"get":{"operationId":"metaScannerSignals","tags":["Public discovery"],"summary":"Machine-readable scanner-signal catalog.","description":"Returns the scanner-signal focus of the agent-readable surface contract: the DISCLOSE_ONLY ceiling, every scanner kind (LLM_ORIGIN, BENCHMARK_OVERLAP, DUPLICATE_DIVERSITY, PROMPT_INJECTION_SIGNAL, SECRET_LEAK_SIGNAL) with bounded-language descriptors + substrate status, and the forbidden-in-automated-outputs vocabulary. Scanner outputs never act as automatic publication blockers, ranking multipliers, payout gates, or eligibility filters. Public, no auth, no DB. Deterministic. cache-control: public, max-age=300.","security":[],"responses":{"200":{"description":"Scanner-signal catalog envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetaScannerSignalsResponse"}}}}}}},"/v1/meta/search-contract":{"get":{"operationId":"metaSearchContract","tags":["Public discovery"],"summary":"Machine-readable search / discovery contract.","description":"Returns the search-and-discovery focus of the agent-readable surface contract: the `/v1/listings` search endpoint reference, ranking-formula summary, the live listing-search hard-filter set (every filter described as HARD_FILTER_ONLY), the malformed-value and unknown-filter-value behavior, and the ranking invariants (`no_hidden_ranking_inputs`, `no_composite_trust_score`, `no_agent_reputation_multiplier`, `no_seller_prestige_relevance_boost`, `no_quality_coefficient` — all true). Public, no auth, no DB. Deterministic. cache-control: public, max-age=300.","security":[],"responses":{"200":{"description":"Search contract envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetaSearchContractResponse"}}}}}}},"/v1/listings":{"get":{"operationId":"listListings","tags":["Public discovery"],"summary":"Search active listings (public).","description":"Paginated search over ACTIVE listings. Supports filters: category, asset_class, file_format, data_purpose, min_price, max_price, tag, industry, rights_block fields, publication_status, jurisdiction, has_doi, max_publication_date_age_days, and free-text `q`. There is no public quality filter or quality sort. Unauthenticated. Responses do not include buyer- or seller-specific state.","security":[],"parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"category","in":"query","schema":{"type":"string"}},{"name":"asset_class","in":"query","schema":{"type":"string","enum":["DATASET","TEXT_ASSET"]}},{"name":"file_format","in":"query","schema":{"type":"string"}},{"name":"data_purpose","in":"query","schema":{"type":"string"}},{"name":"min_price","in":"query","schema":{"type":"integer","minimum":0}},{"name":"max_price","in":"query","schema":{"type":"integer","minimum":0}},{"name":"free_only","in":"query","description":"Friendly agent-side filter; literal 'true' restricts to price_cents=0. Hard filter only.","schema":{"type":"string","enum":["true"]}},{"name":"packet_only","in":"query","description":"Friendly agent-side filter; literal 'true' restricts to packet-overlay listings (packet_manifest IS NOT NULL). Hard filter only.","schema":{"type":"string","enum":["true"]}},{"name":"tag","in":"query","description":"canonical taxonomy tag (kebab-case). Aliases (e.g., `rag` → `rag-corpus`) are rewritten transparently. Unknown / non-canonical tokens return HTTP 400. Filter only — never a relevance boost. See /v1/meta/search-contract → tag_taxonomy for the canonical set.","schema":{"type":"string"}},{"name":"industry_tag","in":"query","description":"Hierarchical industry tag (taxonomy boundary on `.`). Equality + LIKE 'val.%' descendant match.","schema":{"type":"string"}},{"name":"q","in":"query","schema":{"type":"string"},"description":"Free-text search over name, description, and tags."},{"name":"sort","in":"query","schema":{"type":"string","enum":["relevance","price_asc","price_desc","newest"]}},{"name":"has_bundle_assets","in":"query","description":"literal 'true' restricts to bundle-backed listings (listings.packet_bundle_revision_id IS NOT NULL). Filter only.","schema":{"type":"string","enum":["true"]}},{"name":"min_bundle_asset_count","in":"query","description":"minimum bundle asset count. 1..1024. Filter only.","schema":{"type":"integer","minimum":1,"maximum":1024}},{"name":"max_bundle_asset_count","in":"query","description":"maximum bundle asset count. 1..1024. Filter only.","schema":{"type":"integer","minimum":1,"maximum":1024}},{"name":"has_manifest_hash","in":"query","description":"literal 'true' restricts to listings with a populated packet_manifest_hash. Filter only.","schema":{"type":"string","enum":["true"]}},{"name":"has_packet_merkle_root","in":"query","description":"literal 'true' restricts to listings with a populated packet_merkle_root. Filter only.","schema":{"type":"string","enum":["true"]}},{"name":"has_publication_metadata","in":"query","description":"literal 'true' restricts to listings with a listing_publication_metadata row. Filter only.","schema":{"type":"string","enum":["true"]}},{"name":"has_source_url","in":"query","description":"literal 'true' restricts to listings whose underlying dataset declares a source_url. Filter only.","schema":{"type":"string","enum":["true"]}},{"name":"has_evaluated_evidence","in":"query","description":"literal 'true' restricts to listings whose packet_manifest.evidence_refs is a populated object. Disclosure-only — the bucket being declared does not certify quality.","schema":{"type":"string","enum":["true"]}},{"name":"tag_class","in":"query","description":"tag class id (kebab-case). Matches listings whose tags[] overlap with the canonical set for that class. Filter only.","schema":{"type":"string","enum":["model-use","asset-type","domain","modality","format-family","structure","evaluation","integrity","rights","provenance","language","jurisdiction","freshness","standards","buyer-use","safety-posture"]}},{"name":"starter_supply_slug","in":"query","description":"Starter-supply category slug. Hard filter only — never multiplies rank, never enters sort or tiebreaker. Matches listings whose tags[] contain the slug. Invalid slug returns HTTP 400 with a structured validation error.","schema":{"type":"string","enum":["project-governance","claude-md-agent-instructions","repo-playbooks","agent-workflows","evaluation-rubrics","prompt-policy-references","mcp-openapi-integration","public-source-digests","source-backed-research"]}}],"responses":{"200":{"description":"Paginated listing envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListListingsResponse"}}}},"400":{"description":"Request body or query failed schema validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createListing","tags":["Seller"],"summary":"Create a listing (seller).","description":"Requires an authenticated seller org (type SELLER or BOTH). The body must supply EXACTLY ONE delivery target: `dataset_id` for a single-file dataset listing OR `packet_bundle_revision_id` for a finalized packet bundle revision (multi-file). Single-file listings remain the default path; bundle-backed listings carry the same rights / passport / publication-metadata validators. New listings enter PENDING_REVIEW and are only visible to the owning seller and admins until approved. Bundle-backed listings transition to ACTIVE through admin review; entitled buyers fetch them via GET /v1/entitlements/{id}/packet-bundle. Listing price must meet the current marketplace checkout minimum. Rate-limited per organization; a legitimate retry with the same Idempotency-Key + body replays the cached response without consuming an additional rate-limit slot.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateListingRequest"}}}},"responses":{"201":{"description":"Listing created in PENDING_REVIEW.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateListingResponse"}}}},"400":{"description":"Request body or query failed schema validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Authenticated, but the caller is not permitted to perform this operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource does not exist or is not visible to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Error envelope — `ok` is false and `error` carries a stable code + message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests for this org/route in the current window. The `Retry-After` header carries the integer seconds to wait. Response body uses the shared error envelope with `error.code = \"RATE_LIMIT_EXCEEDED\"` and a bounded `retry_after_seconds` field. Legitimate retries with the same Idempotency-Key + body replay the cached response when this status clears.","headers":{"Retry-After":{"description":"Integer seconds the client should wait before retrying.","schema":{"type":"integer","minimum":0}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Service temporarily unavailable — the rate-limit substrate could not confirm capacity safely and the request was held back rather than processed. `Retry-After` carries the integer seconds to wait. Response body uses the shared error envelope with `error.code = \"SERVICE_TEMPORARILY_UNAVAILABLE\"` and a bounded `retry_after_seconds` field.","headers":{"Retry-After":{"description":"Integer seconds the client should wait before retrying.","schema":{"type":"integer","minimum":0}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/listings/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"operationId":"getListing","tags":["Public discovery"],"summary":"Fetch a public listing detail (public).","description":"Returns the public listing detail with declared rights, provenance metadata, intended uses, packet_checks, and evaluation_summary. Public responses do not include a composite quality score or per-dimension quality scores. Only listings in ACTIVE status are visible to the public; callers with the owning seller's auth additionally see their own non-public listings.","security":[],"responses":{"200":{"description":"Listing detail envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingDetailResponse"}}}},"404":{"description":"Resource does not exist or is not visible to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"updateListing","tags":["Seller"],"summary":"Update an owned listing (seller).","description":"Partial update. Sellers may change price (0 for free, or at least the marketplace paid-order minimum), tags, usage_restrictions, content_kind, and rights_block. Packet fields (packet_kind, packet_manifest, version_identifier) are explicitly rejected here. Sellers cannot toggle public_free_access in v0; that field is admin-flip-only via the operator runbook.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateListingRequest"}}}},"responses":{"200":{"description":"Updated listing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateListingResponse"}}}},"400":{"description":"Request body or query failed schema validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Authenticated, but the caller is not permitted to perform this operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource does not exist or is not visible to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/listings/{id}/access-grants":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"post":{"operationId":"createListingAccessGrant","tags":["Public discovery"],"summary":"Mint a public free-access grant (anonymous, rate-limited).","description":"PUBLIC_TOKEN_GRANT_FREE listings only. The listing must be ACTIVE, price_cents = 0, and public_free_access = true. Anonymous; no Bearer required. Per-IP-per-window, per-IP-per-day, and per-listing-global-per-day caps enforced via Redis. Failure-closed on Redis outage (HTTP 503 FREE_ACCESS_TEMPORARILY_UNAVAILABLE). Returns a short-lived bearer-like grant token that must be supplied to GET /v1/listings/:id/free-download. Token is shown once; only its sha256 hash is stored. The response carries Cache-Control: no-store, private and Referrer-Policy: no-referrer; do not log the token or download_url.","security":[],"responses":{"200":{"description":"Grant minted. Body contains grant_id, raw token (return-once), expires_at, download_url, terms_notice, rights_notice, and the rate-limit configuration.","content":{"application/json":{"schema":{"type":"object"}}}},"403":{"description":"Authenticated, but the caller is not permitted to perform this operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource does not exist or is not visible to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"410":{"description":"Error envelope — `ok` is false and `error` carries a stable code + message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Error envelope — `ok` is false and `error` carries a stable code + message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Error envelope — `ok` is false and `error` carries a stable code + message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/listings/{id}/free-download":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"grant","in":"query","required":true,"schema":{"type":"string"}}],"get":{"operationId":"redeemListingFreeDownload","tags":["Public discovery"],"summary":"Redeem a public free-access grant for a short-lived presigned download URL.","description":"Validates the grant token, performs a live listing-eligibility re-check (status, price, public_free_access, dataset/file resolvable), enforces a per-IP-per-minute download rate limit (FAIL CLOSED on Redis outage), and 302-redirects to a fresh presigned URL whose TTL is capped by the grant's remaining TTL and signed_url_ttl_seconds. Each redemption emits FREE_ACCESS_DOWNLOAD_URL_ISSUED; the first redemption transitions the grant ACTIVE → REDEEMED and emits FREE_ACCESS_GRANT_REDEEMED. Issuance is not proof of S3 byte delivery — Graunt does not proxy the file. Response carries Cache-Control: no-store, private and Referrer-Policy: no-referrer.","security":[],"responses":{"302":{"description":"Redirect to a short-lived presigned URL."},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"410":{"description":"Error envelope — `ok` is false and `error` carries a stable code + message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Error envelope — `ok` is false and `error` carries a stable code + message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Error envelope — `ok` is false and `error` carries a stable code + message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/listings/metadata-suggestions/preview":{"post":{"operationId":"previewMetadataSuggestions","tags":["Seller"],"summary":"Deterministic metadata-suggestion preview (Bearer-required).","description":"Reads draft listing metadata (name, description, source_url, asset_class, file_format, category, current_tags, current_industry_tag_codes) and returns deterministic tag / intended-use / industry-tag-code / content-kind suggestions with confidence + reason tokens, plus a bounded `readiness_signals` array (severity `info` or `recommended`) describing sparse fields that weaken agent discovery / hard-filter eligibility / publication review. No external network call. No persistence. NEVER auto-attests rights or legal fields. Sellers must review before applying. Suggestions and readiness signals are never input to search ranking and never block publication. Rate-limited per organization (fail-open: a brief rate-limit substrate outage does not interrupt this low-cost read).","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Suggestions bundle.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Request body or query failed schema validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests for this org/route in the current window. The `Retry-After` header carries the integer seconds to wait. Response body uses the shared error envelope with `error.code = \"RATE_LIMIT_EXCEEDED\"` and a bounded `retry_after_seconds` field. Legitimate retries with the same Idempotency-Key + body replay the cached response when this status clears.","headers":{"Retry-After":{"description":"Integer seconds the client should wait before retrying.","schema":{"type":"integer","minimum":0}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/auth/register":{"post":{"operationId":"authRegister","tags":["Seller"],"summary":"Register a new organization + initial user.","description":"Creates an org of type BUYER, SELLER, or BOTH and returns a JWT for the initial user. Legal acceptance (Terms, AUP, and — for sellers — the Seller Agreement) is recorded transactionally with the registration. Rate-limited per source IP via the auth plugin (10 requests per minute by default). The bucket key is sourced through the edge / origin-auth helper so spoofed `cf-connecting-ip` / `x-forwarded-for` headers do not rotate the bucket unless a trusted-edge posture is enabled.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterRequest"}}}},"responses":{"201":{"description":"Org created; session established.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthResponse"}}}},"400":{"description":"Request body or query failed schema validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Email already in use.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests for this org/route in the current window. The `Retry-After` header carries the integer seconds to wait. Response body uses the shared error envelope with `error.code = \"RATE_LIMIT_EXCEEDED\"` and a bounded `retry_after_seconds` field. Legitimate retries with the same Idempotency-Key + body replay the cached response when this status clears.","headers":{"Retry-After":{"description":"Integer seconds the client should wait before retrying.","schema":{"type":"integer","minimum":0}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/auth/login":{"post":{"operationId":"authLogin","tags":["Seller"],"summary":"Authenticate an existing user and receive a JWT.","description":"Returns a short-lived JWT. Callers must pass the token as `Authorization: Bearer <token>` on subsequent authenticated requests. Rate-limited per source IP via the auth plugin (10 requests per minute by default). The bucket key is sourced through the edge / origin-auth helper so spoofed `cf-connecting-ip` / `x-forwarded-for` headers do not rotate the bucket unless a trusted-edge posture is enabled.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}}},"responses":{"200":{"description":"Authenticated; token returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthResponse"}}}},"400":{"description":"Request body or query failed schema validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests for this org/route in the current window. The `Retry-After` header carries the integer seconds to wait. Response body uses the shared error envelope with `error.code = \"RATE_LIMIT_EXCEEDED\"` and a bounded `retry_after_seconds` field. Legitimate retries with the same Idempotency-Key + body replay the cached response when this status clears.","headers":{"Retry-After":{"description":"Integer seconds the client should wait before retrying.","schema":{"type":"integer","minimum":0}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/auth/stripe/connect":{"post":{"operationId":"startStripeConnect","tags":["Seller"],"summary":"Begin Stripe Connect onboarding for a seller org.","description":"Returns a Stripe-hosted onboarding URL. The caller must be a seller or BOTH org. Completion is required before the seller can receive payouts; listing creation does not require it. The alpha marketplace is Stripe-only.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Stripe onboarding URL issued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StripeConnectResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Authenticated, but the caller is not permitted to perform this operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/purchases":{"post":{"operationId":"initiatePurchase","tags":["Authenticated purchase"],"summary":"Initiate a FULL purchase of an ACTIVE listing.","description":"Creates a PaymentIntent via Stripe and returns the client secret. Complete the intent via Stripe's client SDK; Graunt creates the entitlement on webhook confirmation. Idempotent on the caller-supplied `idempotency_key`. Order totals are subject to the current marketplace checkout minimum.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InitiatePurchaseRequest"}}}},"responses":{"200":{"description":"Purchase intent created (or the prior intent for this idempotency_key was returned).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InitiatePurchaseResponse"}}}},"400":{"description":"Request body or query failed schema validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Authenticated, but the caller is not permitted to perform this operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource does not exist or is not visible to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/purchases/{id}/request-refund":{"post":{"operationId":"requestRefund","tags":["Authenticated purchase"],"summary":"Request a refund for an eligible completed purchase.","description":"Creates a refund_request row in REQUESTED state for an eligible buyer-owned, COMPLETED, refund_status=NONE purchase. Idempotent on the body-level `idempotency_key` via the shared idempotency reservation table. One refund_request per purchase ever — re-requests after any terminal state return 422 `refund_request_already_exists`. Cross-org access surfaces as 404 (no leak). Audit event REFUND_REQUESTED records only IDs + booleans (Hard Rule 7); buyer's reason text stays in `refund_requests.buyer_reason` only.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["buyer_reason","idempotency_key"],"properties":{"buyer_reason":{"type":"string","minLength":1,"maxLength":2000},"idempotency_key":{"type":"string","minLength":1,"maxLength":255}}}}}},"responses":{"200":{"description":"Idempotent replay — same idempotency_key + same fingerprint returns the prior 201 body."},"201":{"description":"Refund request created."},"400":{"description":"Request body or query failed schema validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource does not exist or is not visible to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Idempotency-key conflict (same key + different fingerprint) or in-progress reservation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Purchase not eligible (status != COMPLETED, refund_status != NONE) or refund_request already exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/purchases/{id}/refund-request":{"get":{"operationId":"getRefundRequest","tags":["Authenticated purchase"],"summary":"Fetch the buyer-visible refund-request state for a purchase.","description":"Org-scoped lookup. Returns `{ refund_request: null }` when no request exists; otherwise the current state, buyer_reason, decision_note (admin-authored, may be shown to the buyer on DENIED), and timestamps.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Refund request state (or null when none)."},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/entitlements/{id}/packet-bundle":{"get":{"operationId":"getEntitlementPacketBundle","tags":["Authenticated retrieval"],"summary":"Fetch every asset in a bundle-backed entitlement as one short-lived signed-URL list (buyer / entitled agent).","description":"Buyer multi-asset bundle delivery. Returns the immutable packet bundle revision pinned on the entitlement plus a fresh presigned URL per asset (TTL 600 seconds). Each successful call atomically decrements `download_count` once (per-call semantics — bundle fanout does NOT multiply the counter). Per-asset audit events record IDs / counts / hashes only — never URLs. Cross-org access collapses to 404. Single-file entitlements receive 422 ENTITLEMENT_NOT_BUNDLE_BACKED with `details.redirect_path` pointing at /v1/entitlements/{id}/download. Response headers carry Cache-Control: no-store, private and Referrer-Policy: no-referrer.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Bundle revision manifest + per-asset presigned-URL list. All URLs share one expires_at moment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntitlementPacketBundleResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Authenticated, but the caller is not permitted to perform this operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource does not exist or is not visible to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Entitlement not bundle-backed (redirect to /:id/download), unsupported scope, or download limit reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Storage presign failure or missing bundle revision row. Counter NOT decremented; no audit emitted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/entitlements/{id}/download":{"get":{"operationId":"downloadEntitlement","tags":["Authenticated retrieval"],"summary":"Fetch a presigned download URL for an owned entitlement (buyer).","description":"Returns a presigned URL the caller can fetch directly for a bounded TTL (currently 600 seconds; <= 15 minutes per platform rule). Each call atomically increments `download_count` and fails with 422 DOWNLOADS_EXHAUSTED when the max is reached. Only FULL-scope entitlements support download today. Bundle-backed entitlements receive 422 ENTITLEMENT_BUNDLE_BACKED here with `details.redirect_path` pointing at /v1/entitlements/{id}/packet-bundle. When the underlying packet listing is signed, the response carries six X-Graunt-* headers identical to those served by GET /v1/listings/{id}/manifest, enabling buyers to verify (manifest_hash, merkle_root, signed_at, signature, key_id, custody_tier) at download time.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Presigned download URL + remaining-quota envelope. Six X-Graunt-* headers present when the listing is signed.","headers":{"X-Graunt-Manifest-Hash":{"description":"sha256:<64hex> packet manifest hash (signed listings only).","schema":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"}},"X-Graunt-Merkle-Root":{"description":"sha256:<64hex> packet Merkle root (signed listings only).","schema":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"}},"X-Graunt-Signed-At":{"description":"ISO-8601 UTC millisecond timestamp from published_manifests.signed_at (signed listings only).","schema":{"type":"string","format":"date-time"}},"X-Graunt-Signature":{"description":"Base64 Ed25519 signature over manifest_hash || '|' || merkle_root || '|' || signed_at_iso (signed listings only).","schema":{"type":"string"}},"X-Graunt-Key-Id":{"description":"Signer key identifier (signed listings only).","schema":{"type":"string","pattern":"^skey_[A-Za-z0-9]{22}$"}},"X-Graunt-Custody-Tier":{"description":"Custody-tier disclosure (signed listings only).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DownloadResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Authenticated, but the caller is not permitted to perform this operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource does not exist or is not visible to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Download limit reached or entitlement scope not supported.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Integrity data mismatch — signed listing is missing the matching published_manifests row. Counter NOT decremented.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/datasets":{"post":{"operationId":"uploadDataset","tags":["Seller"],"summary":"Upload a dataset file with metadata (seller).","description":"Multipart upload. The asset is stored, the row count (for DATASET) or excerpt (for TEXT_ASSET) is extracted, and packet checks are recorded asynchronously. Poll GET /v1/datasets/{id} to track qc_status.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file","name","description","category","asset_class","data_purpose","intended_uses","rights_attestation"],"properties":{"file":{"type":"string","format":"binary"},"name":{"type":"string"},"description":{"type":"string","minLength":50},"category":{"type":"string"},"asset_class":{"type":"string","enum":["DATASET","TEXT_ASSET"]},"data_purpose":{"type":"string","description":"JSON-encoded array of declared purposes."},"intended_uses":{"type":"string","description":"JSON-encoded array of intended-use strings."},"rights_attestation":{"type":"string","enum":["true","false"]}}}}}},"responses":{"201":{"description":"Dataset accepted for QC.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadDatasetResponse"}}}},"400":{"description":"Request body or query failed schema validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Authenticated, but the caller is not permitted to perform this operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"File exceeds max upload size.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"operationId":"listMyDatasets","tags":["Authenticated retrieval"],"summary":"List datasets owned by the caller's org (seller).","description":"Paginated list of the caller's own datasets. Includes lifecycle status, QC state, and file metadata. Does NOT include buyer data or other sellers' datasets.","security":[{"bearerAuth":[]}],"parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"status","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated dataset envelope scoped to the caller's org.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListDatasetsResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Authenticated, but the caller is not permitted to perform this operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/seller/listings":{"get":{"operationId":"listSellerListings","tags":["Seller"],"summary":"List the caller's listings (seller persona).","description":"Paginated, org-scoped inventory of listings owned by the caller. SELLER and BOTH only. Returns denormalized fields per row including delivery_kind (SINGLE_FILE | PACKET_BUNDLE) and packet_bundle_revision_id when applicable. Sorted by created_at DESC. Backs the seller-dashboard \"My Listings\" panel.","security":[{"bearerAuth":[]}],"parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"per_page","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"Paginated listing envelope scoped to the caller's org.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSellerListingsResponse"}}}},"400":{"description":"Request body or query failed schema validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Authenticated, but the caller is not permitted to perform this operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/seller/listings/{id}":{"get":{"operationId":"getSellerListingDetail","tags":["Seller"],"summary":"Get seller-private listing detail (all owned statuses).","description":"Returns the full seller-private detail for a single listing owned by the caller's org, across ALL statuses (PENDING_REVIEW, ACTIVE, PAUSED, ARCHIVED, REJECTED, SUSPENDED, NEEDS_REFINEMENT). Distinct from public GET /v1/listings/{id} which is hard-gated to ACTIVE. Cross-org listings return 404 (no 403 leak). The response carries validation_findings (manifest-level findings projected from packet_validation_report), last_admin_review (bounded summary of the most-recent admin event in the closed allowlist; never carries actor identity or raw payload), and available_actions.can_resubmit_for_review.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Seller listing detail.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSellerListingDetailResponse"}}}},"400":{"description":"Request body or query failed schema validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Authenticated, but the caller is not permitted to perform this operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Listing does not exist or is owned by another org.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/seller/listings/{id}/packet-bundle":{"get":{"operationId":"getSellerListingPacketBundle","tags":["Seller"],"summary":"Get seller-private packet-bundle detail for a listing.","description":"Returns the bundle's frozen-revision metadata + per-asset rows (sorted by ordering) for bundle-backed listings owned by the caller. Single-file listings, cross-org listings, and unknown listing ids all return 404 — existence is never leaked. NEVER includes s3_key, download_url, presigned URLs, or X-Amz-* artefacts. Mirrors the schema_version=2 logical/physical asset grouping used by the buyer-facing manifest endpoint.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Seller listing packet-bundle detail.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSellerListingPacketBundleResponse"}}}},"400":{"description":"Request body or query failed schema validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Authenticated, but the caller is not permitted to perform this operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Listing not found, owned by another org, or single-file (no bundle).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/seller/listings/{id}/resubmit":{"post":{"operationId":"resubmitSellerListing","tags":["Seller"],"summary":"Resubmit a NEEDS_REFINEMENT listing back to PENDING_REVIEW.","description":"Seller-driven NEEDS_REFINEMENT → PENDING_REVIEW transition. Runs the manifest-only publish-gate validators (structure + presence + coherence) on the listing's stored packet_manifest BEFORE flipping status. If any finding has blocks_publish=true, returns 409 with code LISTING_RESUBMIT_BLOCKED + bounded findings array; status stays NEEDS_REFINEMENT and no audit row is written. On success, emits LISTING_RESUBMITTED audit and returns the refreshed seller-detail. Idempotency-Key header (16-128 chars, [A-Za-z0-9_-]) routes through the existing reservation service; same key + same fingerprint replays.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","minLength":16,"maxLength":128,"pattern":"^[A-Za-z0-9_-]+$"}}],"responses":{"200":{"description":"Status flipped to PENDING_REVIEW; refreshed seller-detail returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSellerListingDetailResponse"}}}},"400":{"description":"Request body or query failed schema validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Authenticated, but the caller is not permitted to perform this operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Listing not found or owned by another org.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Wrong status (not NEEDS_REFINEMENT) OR blocking validation findings remain (code: LISTING_RESUBMIT_BLOCKED) OR Idempotency-Key conflict.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/listings/{id}/validate-manifest":{"post":{"operationId":"validateListingManifestDryRun","tags":["Seller"],"summary":"Read-only dry-run of manifest validation for a seller-owned listing.","description":"Composes the same packet-manifest validators (structure + presence + coherence) used by the publish gate WITHOUT mutating the listing. NO listings.updated_at change. NO listings.validation_status change. NO audit_log INSERT. NO packet_bundle mutation. Body is optional; when provided, packet_manifest / version_identifier / packet_kind override the listing's stored values for the dry-run only. Empty body validates the listing as-is. Status gate accepts PENDING_REVIEW or NEEDS_REFINEMENT.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"packet_manifest":{},"packet_kind":{"type":["string","null"]},"version_identifier":{"type":["string","null"]}}}}}},"responses":{"200":{"description":"Dry-run completed (findings array may be empty or non-empty; would_block_publish indicates publish-gate outcome).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidateListingManifestDryRunResponse"}}}},"400":{"description":"Request body or query failed schema validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Authenticated, but the caller is not permitted to perform this operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Listing not found or owned by another org.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Wrong status (not PENDING_REVIEW or NEEDS_REFINEMENT).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/seller/packet-bundles":{"get":{"operationId":"listSellerPacketBundles","tags":["Seller"],"summary":"List the caller's packet bundles (seller persona).","description":"Paginated, org-scoped list of packet bundles owned by the caller, with each bundle's latest revision metadata inline (revision_number, manifest_sha256, total_bytes, asset_count, frozen_at). Backs the listing-create wizard's bundle-picker step. SELLER and BOTH only. When `finalized=true` (the wizard's primary use case), only bundles that have at least one frozen revision are returned. Never returns presigned URLs or s3_keys.","security":[{"bearerAuth":[]}],"parameters":[{"name":"finalized","in":"query","schema":{"type":"string","enum":["true","false"]}},{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"per_page","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}],"responses":{"200":{"description":"Paginated packet bundle envelope scoped to the caller's org.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSellerPacketBundlesResponse"}}}},"400":{"description":"Request body or query failed schema validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Authenticated, but the caller is not permitted to perform this operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/seller/payouts":{"get":{"operationId":"listMyPayouts","tags":["Seller"],"summary":"List payout splits for the caller's seller org.","description":"Read-only view of per-purchase payout splits (PENDING, HELD, TRANSFERRED, FAILED). Payouts are individual Stripe Transfers; a 72-hour hold applies to first-time sellers.","security":[{"bearerAuth":[]}],"parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"per_page","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"Paginated payout envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListPayoutsResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Authenticated, but the caller is not permitted to perform this operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/seller/signing-keys":{"post":{"operationId":"registerSigningKey","tags":["Seller"],"summary":"Register a server-generated Ed25519 signing key (seller).","description":"Server generates an Ed25519 keypair; the public key is exposed and the private key is stored encrypted at rest under the per-deploy KEK (server-assisted-alpha custody). Body is empty — caller-supplied keys are not accepted in alpha. Auth: orgType ∈ {SELLER, BOTH}.","security":[{"bearerAuth":[]}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"201":{"description":"Public view of the new key (no envelope fields).","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Authenticated, but the caller is not permitted to perform this operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Request body or query failed schema validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"operationId":"listMySigningKeys","tags":["Seller"],"summary":"List the caller's signing keys (any status).","description":"Returns ACTIVE, ROTATED, and REVOKED entries owned by the caller. Envelope fields (encrypted_private_key_b64, IV, tag) are never returned.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Owner view envelope.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Authenticated, but the caller is not permitted to perform this operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/seller/signing-keys/{keyId}/rotate":{"parameters":[{"name":"keyId","in":"path","required":true,"schema":{"type":"string","pattern":"^skey_[A-Za-z0-9]{22}$"}}],"post":{"operationId":"rotateSigningKey","tags":["Seller"],"summary":"Rotate the named signing key (atomic).","description":"Marks the named ACTIVE key as ROTATED and creates a new ACTIVE key in the same call (integrity-model §4). Old signatures continue to verify against the rotated public key.","security":[{"bearerAuth":[]}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"201":{"description":"Rotated + new active key views.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Authenticated, but the caller is not permitted to perform this operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource does not exist or is not visible to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Request body or query failed schema validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/seller/signing-keys/{keyId}/revoke":{"parameters":[{"name":"keyId","in":"path","required":true,"schema":{"type":"string","pattern":"^skey_[A-Za-z0-9]{22}$"}}],"post":{"operationId":"revokeSigningKey","tags":["Seller"],"summary":"Revoke the named signing key (forward-only).","description":"Marks the key REVOKED. Signatures produced before revocation remain valid (integrity-model §4 forward-only revocation). Does not require KEK access.","security":[{"bearerAuth":[]}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","minLength":1,"maxLength":256}}}}}},"responses":{"200":{"description":"Public view of the revoked key.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Authenticated, but the caller is not permitted to perform this operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource does not exist or is not visible to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Request body or query failed schema validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/meta/signing-keys":{"get":{"operationId":"metaSigningKeys","tags":["Public discovery"],"summary":"Public registry of signing keys for buyer verification.","description":"Returns ACTIVE, ROTATED, and REVOKED public keys across all orgs. Buyers use this endpoint to obtain the public key referenced by `X-Graunt-Key-Id` on a signed response, then verify the tuple `manifest_hash || '|' || merkle_root || '|' || signed_at_iso`. Public — no auth.","security":[],"responses":{"200":{"description":"Signing-key catalog (no envelope fields).","content":{"application/json":{"schema":{"type":"object"}}}},"503":{"description":"Database unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/packet-upload-sessions":{"post":{"operationId":"createPacketUploadSession","tags":["Seller"],"summary":"Create a packet upload session (seller).","description":"Creates a transient OPEN session that gathers asset uploads before freezing into a `packet_bundle_revision`. Either supply `name` (and optional `description`) to create a new bundle, or supply `bundle_id` to attach to an existing bundle in the caller's org. `idempotency_key` is required and replays an in-progress or completed call deterministically via the existing reservation/replay envelope shared with other write routes. Rate-limited per organization; a legitimate retry with the same Idempotency-Key + body replays the cached response without consuming an additional rate-limit slot. SELLER and BOTH only.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["idempotency_key"],"properties":{"idempotency_key":{"type":"string","minLength":32,"maxLength":128},"bundle_id":{"type":"string","format":"uuid"},"name":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":4000},"max_asset_count":{"type":"integer","minimum":1,"maximum":256},"max_total_bytes":{"type":"integer","minimum":1}}}}}},"responses":{"201":{"description":"Session created.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Authenticated, but the caller is not permitted to perform this operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource does not exist or is not visible to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_key conflict or bundle archived.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Request body or query failed schema validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests for this org/route in the current window. The `Retry-After` header carries the integer seconds to wait. Response body uses the shared error envelope with `error.code = \"RATE_LIMIT_EXCEEDED\"` and a bounded `retry_after_seconds` field. Legitimate retries with the same Idempotency-Key + body replay the cached response when this status clears.","headers":{"Retry-After":{"description":"Integer seconds the client should wait before retrying.","schema":{"type":"integer","minimum":0}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Service temporarily unavailable — the rate-limit substrate could not confirm capacity safely and the request was held back rather than processed. `Retry-After` carries the integer seconds to wait. Response body uses the shared error envelope with `error.code = \"SERVICE_TEMPORARILY_UNAVAILABLE\"` and a bounded `retry_after_seconds` field.","headers":{"Retry-After":{"description":"Integer seconds the client should wait before retrying.","schema":{"type":"integer","minimum":0}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/packet-upload-sessions/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"operationId":"getPacketUploadSession","tags":["Authenticated retrieval"],"summary":"Read a packet upload session's state, asset list, and last_validation_result.","description":"Org-scoped read. Returns the session state machine value, the registered upload-session-asset rows (without presigned PUT URLs), the most recent finalize attempt's findings (when failed), and the bundle_revision_id (when finalized).","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Session view.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource does not exist or is not visible to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"abandonPacketUploadSession","tags":["Seller"],"summary":"Abandon a packet upload session.","description":"Transitions an OPEN/FINALIZING session to ABANDONED. If the bundle has zero revisions and no other open sessions reference it, the session row and the empty bundle are deleted in the same transaction (no orphans).","security":[{"bearerAuth":[]}],"responses":{"204":{"description":"Session abandoned."},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Authenticated, but the caller is not permitted to perform this operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource does not exist or is not visible to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Session already finalized — abandon not permitted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/packet-upload-sessions/{id}/assets":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"post":{"operationId":"registerPacketUploadAsset","tags":["Seller"],"summary":"Register an asset in a packet upload session and receive a presigned PUT URL.","description":"Allocates a stable `asset_id` (preserved through finalize), constructs the transient S3 key, and returns a single-part presigned PUT URL with TTL ≤ 900 s. The seller PUTs object bytes directly to S3 over the URL's lifetime. Concurrent registers on the same `(session_id, ordering)` rejected with 422 DUPLICATE_ORDERING.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["original_filename","declared_size_bytes","declared_role","ordering","file_format"],"properties":{"original_filename":{"type":"string","minLength":1,"maxLength":255},"declared_size_bytes":{"type":"integer","minimum":0},"declared_content_sha256":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"},"declared_role":{"type":"string","enum":["PRIMARY","SUPPORTING","EVIDENCE","MANIFEST","LEGAL_NOTICE"]},"ordering":{"type":"integer","minimum":0,"maximum":255},"file_format":{"type":"string","enum":["CSV","JSON","PARQUET","TEXT","JSONL","PDF"]}}}}}},"responses":{"201":{"description":"Asset registered; presigned PUT URL returned.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Authenticated, but the caller is not permitted to perform this operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource does not exist or is not visible to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Session not in OPEN state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Request body or query failed schema validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/packet-upload-sessions/{id}/assets/{assetId}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"assetId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"delete":{"operationId":"deletePacketUploadAsset","tags":["Seller"],"summary":"Remove a registered asset from a packet upload session.","description":"Used to fix a failed-finalize finding (e.g., DELETE the offending asset, register a replacement at the same ordering, retry finalize). Already-deleted assets return 204 idempotently. The transient S3 object remains (lifecycle eventually cleans it up).","security":[{"bearerAuth":[]}],"responses":{"204":{"description":"Asset removed (or already absent)."},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Authenticated, but the caller is not permitted to perform this operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource does not exist or is not visible to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Session not in OPEN state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/packet-upload-sessions/{id}/finalize":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"post":{"operationId":"finalizePacketUploadSession","tags":["Seller"],"summary":"Validate, hash, and freeze a packet bundle revision.","description":"Atomic OPEN→FINALIZING transition is the concurrency gate. Streams sha256 over each S3 object, runs eight deterministic checks (BUNDLE_EMPTY / BUNDLE_TOO_MANY_ASSETS / ASSET_FORMAT_DISALLOWED / ASSET_EMPTY / ASSET_TOO_LARGE / BUNDLE_OVERSIZE / BUNDLE_PRIMARY_INVARIANT / BUNDLE_DUPLICATE_CONTENT / ASSET_BYTE_SIZE_MISMATCH / ASSET_CONTENT_SHA_MISMATCH / ASSET_OBJECT_MISSING), copies objects to the frozen bundle prefix, and inserts the immutable revision under a SELECT FOR UPDATE on `packet_bundle`. On validation failure the session returns to OPEN with `last_validation_result` populated; the seller may DELETE/replace assets and retry. Rate-limited per organization; a legitimate retry with the same Idempotency-Key replays the cached response without consuming an additional rate-limit slot.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["idempotency_key"],"properties":{"idempotency_key":{"type":"string","minLength":32,"maxLength":128}}}}}},"responses":{"200":{"description":"Bundle revision frozen (or idempotent replay returned the existing revision).","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Authenticated, but the caller is not permitted to perform this operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource does not exist or is not visible to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Session is not OPEN (concurrent finalize race lost, or session already terminal).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"VALIDATION_FAILED — error.details.findings carries the failing check.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests for this org/route in the current window. The `Retry-After` header carries the integer seconds to wait. Response body uses the shared error envelope with `error.code = \"RATE_LIMIT_EXCEEDED\"` and a bounded `retry_after_seconds` field. Legitimate retries with the same Idempotency-Key + body replay the cached response when this status clears.","headers":{"Retry-After":{"description":"Integer seconds the client should wait before retrying.","schema":{"type":"integer","minimum":0}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Service temporarily unavailable — the rate-limit substrate could not confirm capacity safely and the request was held back rather than processed. `Retry-After` carries the integer seconds to wait. Response body uses the shared error envelope with `error.code = \"SERVICE_TEMPORARILY_UNAVAILABLE\"` and a bounded `retry_after_seconds` field.","headers":{"Retry-After":{"description":"Integer seconds the client should wait before retrying.","schema":{"type":"integer","minimum":0}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/packet-bundles/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"operationId":"getPacketBundle","tags":["Authenticated retrieval"],"summary":"Read a packet bundle and its revision (seller / admin).","description":"Org-scoped read. Returns the bundle metadata and either the latest revision (default) or a specific `revision_number` when supplied as a query parameter. Each revision view includes the asset list (id, file_format, file_size_bytes, content_sha256, ordering, asset_role, original_filename) sorted by ordering.","security":[{"bearerAuth":[]}],"parameters":[{"name":"revision_number","in":"query","required":false,"schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"Bundle + revision view.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource does not exist or is not visible to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/listings/{id}/manifest":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"operationId":"getListingManifest","tags":["Public discovery"],"summary":"Fetch the canonical packet manifest bytes (public).","description":"Returns the canonical UTF-8 bytes of `listings.packet_manifest`. The body's SHA-256 equals `X-Graunt-Manifest-Hash` (when signed) or can be recomputed by the buyer (always). When signed, six X-Graunt-* headers are emitted (Manifest-Hash, Merkle-Root, Signed-At, Signature, Key-Id, Custody-Tier). Public — no auth.","security":[],"responses":{"200":{"description":"Canonical manifest bytes.","headers":{"X-Graunt-Manifest-Hash":{"description":"sha256:<64hex> over the response body bytes (signed responses).","schema":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"}},"X-Graunt-Merkle-Root":{"description":"sha256:<64hex> Merkle root over delivery artifact (signed responses).","schema":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"}},"X-Graunt-Signed-At":{"description":"ISO-8601 UTC millisecond timestamp from published_manifests.signed_at (signed responses).","schema":{"type":"string","format":"date-time"}},"X-Graunt-Signature":{"description":"Base64 Ed25519 signature over manifest_hash || '|' || merkle_root || '|' || signed_at_iso (signed responses).","schema":{"type":"string"}},"X-Graunt-Key-Id":{"description":"Signer key identifier (skey_<22 base62>) — look up public key via /v1/meta/signing-keys.","schema":{"type":"string","pattern":"^skey_[A-Za-z0-9]{22}$"}},"X-Graunt-Custody-Tier":{"description":"Custody-tier disclosure. Alpha always emits server_assisted_alpha.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object"}}}},"404":{"description":"Resource does not exist or is not visible to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Integrity data mismatch — listing is signed but published_manifests row is missing or divergent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/meta/capabilities":{"get":{"operationId":"metaArciCapabilities","tags":["Public discovery"],"summary":"6-state capability registry (P6-ARCI-2).","description":"Returns the LIVE/PREVIEW/PLANNED/DISABLED/RESERVED/ABSENT state for every Graunt capability. Public, no auth, no DB, deterministic. cache-control: public, max-age=300.","security":[],"responses":{"200":{"description":"Capability registry.","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/v1/meta/arci-surfaces":{"get":{"operationId":"metaArciSurfaces","tags":["Public discovery"],"summary":"ARCI pages + machine operations index (P6-ARCI-2).","description":"Returns the ARCI page registry + operationId registry with capability state per entry. Public, no auth, no DB. cache-control: public, max-age=300.","security":[],"responses":{"200":{"description":"ARCI surface index.","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/v1/meta/modals":{"get":{"operationId":"metaArciModals","tags":["Public discovery"],"summary":"22 modal kinds with truthful summaries (P6-ARCI-2).","description":"Returns the 22 ARCI modal kinds with title + body summary + capability key + capability state. Public, no auth, no DB. cache-control: public, max-age=300.","security":[],"responses":{"200":{"description":"Modal registry.","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/v1/meta/rights-model":{"get":{"operationId":"metaArciRightsModel","tags":["Public discovery"],"summary":"Output rights vocabulary (P6-ARCI-2).","description":"Returns the 6 posture enums + 15 rights-decline codes that back per-listing declarative output rights. Public, no auth, no DB. cache-control: public, max-age=300.","security":[],"responses":{"200":{"description":"Rights model vocabulary.","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/v1/meta/denial-codes":{"get":{"operationId":"metaArciDenialCodes","tags":["Public discovery"],"summary":"15 closed-enum denial codes (P6-ARCI-2).","description":"Returns the 15 closed-enum denial codes returned by entitled access denial paths, with descriptions. Public, no auth, no DB. cache-control: public, max-age=300.","security":[],"responses":{"200":{"description":"Denial codes catalog.","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/v1/meta/receipt-kinds":{"get":{"operationId":"metaArciReceiptKinds","tags":["Public discovery"],"summary":"14 receipt kinds + payload allowlists (P6-ARCI-2).","description":"Returns the 14 receipt kinds with per-kind payload field allowlists + 3 proof kinds + 2 statuses. The allowlist is the no-leak truth for what each receipt payload may carry. Public, no auth, no DB. cache-control: public, max-age=300.","security":[],"responses":{"200":{"description":"Receipt kinds catalog.","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/v1/receipts":{"get":{"operationId":"listReceipts","tags":["Authenticated retrieval"],"security":[{"bearerAuth":[]}],"summary":"List receipts for the auth org (P6-ARCI-2 P1).","description":"Returns audit-grade receipts scoped to the auth org. Filterable by kind / status / delivery_id / entitlement_id. Pagination via page + per_page. Read-only — append-only invariant preserved.","parameters":[{"in":"query","name":"page","schema":{"type":"integer","minimum":1}},{"in":"query","name":"per_page","schema":{"type":"integer","minimum":1,"maximum":100}},{"in":"query","name":"kind","schema":{"type":"string"}},{"in":"query","name":"status","schema":{"type":"string"}},{"in":"query","name":"delivery_id","schema":{"type":"string","format":"uuid"}},{"in":"query","name":"entitlement_id","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Receipt page.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Request body or query failed schema validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/receipts/{id}":{"get":{"operationId":"getReceipt","tags":["Authenticated retrieval"],"security":[{"bearerAuth":[]}],"summary":"Get a single receipt by id (P6-ARCI-2 P1).","description":"Returns a single receipt scoped to the auth org. 404 on cross-org id or unknown id (no 403 leak).","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Receipt detail.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource does not exist or is not visible to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/query/quote":{"post":{"operationId":"quoteQuery","tags":["Authenticated retrieval"],"security":[{"bearerAuth":[]}],"summary":"Quote a query class against a listing (P6-ARCI-2 P3).","description":"Returns a budget quote (max cents, max calls, expires_at) for the given query class + listing. Emits a query_quote receipt as evidence. STUB_VERIFIER pricing at this slice; LIVE_VERIFIER gated by FEATURE_LIVE_VERIFIER (default OFF).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["listing_id"],"properties":{"listing_id":{"type":"string","format":"uuid"},"query_class":{"type":"string","enum":["STANDARD","BURST","ENTERPRISE_DEDICATED","TRIAL"]}}}}}},"responses":{"200":{"description":"Quote envelope.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Request body or query failed schema validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/query/ask":{"post":{"operationId":"askQuery","tags":["Authenticated retrieval"],"security":[{"bearerAuth":[]}],"summary":"Ask a query under STUB_VERIFIER (P6-ARCI-2 P3).","description":"Returns a deterministic stub answer, the answer hash, cited-source count, and the verifier kind. Emits an answer receipt. STUB_VERIFIER at this slice — no LLM, no transport. LIVE_VERIFIER is gated by FEATURE_LIVE_VERIFIER (default OFF) and a separate locked decision.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["listing_id","query"],"properties":{"listing_id":{"type":"string","format":"uuid"},"query":{"type":"string","minLength":1,"maxLength":4096},"rights_basis_ref":{"type":"string"}}}}}},"responses":{"200":{"description":"Answer envelope.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Request body or query failed schema validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/splices":{"get":{"operationId":"listSplices","tags":["Authenticated retrieval"],"security":[{"bearerAuth":[]}],"summary":"List splices for the auth org (P6-ARCI-2 P4).","description":"Returns the auth org's splices, ordered by creation time DESC. Limited to the first 100 rows at this slice (pagination opens at a follow-on commit).","responses":{"200":{"description":"Splice list.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createSplice","tags":["Authenticated retrieval"],"security":[{"bearerAuth":[]}],"summary":"Create a splice from a parent listing (P6-ARCI-2 P4).","description":"Accepts the 3 LIVE splice kinds (ROW_SPLICE, JURISDICTION_SPLICE, ANSWER_CONTEXT_SPLICE). Rejects the 8 RESERVED kinds with 409 + CAPABILITY_NOT_LIVE. Writes a splice row in PREVIEW_NOT_LIVE status + emits a splice receipt as evidence.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["parent_listing_id","splice_kind","splice_hash","rights_basis_ref"],"properties":{"parent_listing_id":{"type":"string","format":"uuid"},"splice_kind":{"type":"string"},"splice_hash":{"type":"string","pattern":"^[0-9a-f]{64}$"},"row_count":{"type":"integer","nullable":true},"size_bytes":{"type":"integer","nullable":true},"jurisdiction_scope":{"type":"array","items":{"type":"string"}},"rights_basis_ref":{"type":"string"},"notes":{"type":"string","nullable":true}}}}}},"responses":{"201":{"description":"Splice created.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Request body or query failed schema validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"CAPABILITY_NOT_LIVE — splice_kind is RESERVED at this slice.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/output-rights/{listing_id}":{"get":{"operationId":"getOutputRights","tags":["Public discovery"],"summary":"Public output-rights for a listing (P6-ARCI-2 P2).","description":"Returns the per-listing declarative output rights (6 postures + 3 boolean fields + jurisdiction allow/deny + rights_decline_codes + version) or null when no row exists. Public — agents and humans read this BEFORE purchase to plan post-delivery use.","security":[],"parameters":[{"in":"path","name":"listing_id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Output rights row or null.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Request body or query failed schema validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/agents/principals":{"get":{"operationId":"listAgentPrincipals","tags":["Authenticated retrieval"],"summary":"List agent principals owned by the authenticated org (P6-ARCI-2 P5).","description":"Returns the org's agent principals with default PREVIEW_NOT_LIVE status and HUMAN_APPROVAL_REQUIRED approval_policy. Agent identity is in PREVIEW; live MCP transport remains PLANNED (gated by FEATURE_P6_ARCI_MCP_LIVE).","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Array of agent principals + capability state metadata.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createAgentPrincipal","tags":["Authenticated retrieval"],"summary":"Create an agent principal (PREVIEW_NOT_LIVE default).","description":"Creates a new agent principal owned by the authenticated org. Default status PREVIEW_NOT_LIVE; default approval_policy HUMAN_APPROVAL_REQUIRED per HUMAN_APPROVAL_REQUIRED policy. Slug must match ^[a-z0-9][a-z0-9-]{0,63}$. SLUG_TAKEN (400) returned on (org_id, slug) collision.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"201":{"description":"Created principal id + state.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Request body or query failed schema validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/agents/principals/{id}":{"get":{"operationId":"getAgentPrincipal","tags":["Authenticated retrieval"],"summary":"Get an agent principal by id (org-scoped).","description":"Returns the agent principal row with status + approval_policy + spend caps. Org-scoped: cross-org id returns 404 (no existence disclosure). Capability state PREVIEW.","security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Agent principal row + state.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource does not exist or is not visible to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/agents/credentials":{"get":{"operationId":"listAgentCredentials","tags":["Authenticated retrieval"],"summary":"List agent credentials for the authenticated org (no plaintext).","description":"Returns sha256 keyHash-backed credentials with display-only keyPrefix. Plaintext is shown ONLY at issuance and never persisted.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Array of credentials (no plaintext).","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"issueAgentCredential","tags":["Authenticated retrieval"],"summary":"Issue a new agent credential (plaintext returned ONCE).","description":"Mints a `grnt_agt_<48 hex>` plaintext key, persists sha256 keyHash + 12-char display keyPrefix, and returns the plaintext in the 201 response body. Plaintext is not retrievable afterwards. The agent_principal_id must belong to the authenticated org.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"201":{"description":"Issued credential with plaintext key (shown once).","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Request body or query failed schema validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource does not exist or is not visible to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/agents/credentials/{id}/revoke":{"post":{"operationId":"revokeAgentCredential","tags":["Authenticated retrieval"],"summary":"Revoke an ACTIVE agent credential.","description":"Transitions credential status to REVOKED with revoked_at + bounded revoked_reason ≤240 chars. Already-revoked / cross-org credentials return 404.","security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Revocation acknowledged.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource does not exist or is not visible to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/agents/{agent_id}/manifest":{"get":{"operationId":"getAgentAccessManifest","tags":["Authenticated retrieval"],"summary":"Get the most-recent access manifest for an agent principal.","description":"Returns the latest (PREVIEW_NOT_LIVE / PLANNED_NOT_ACTIVE / ACTIVE) manifest for the agent. 404 when no manifest is set; the response message points the caller at PUT to create one.","security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"agent_id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Manifest row + capability state.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource does not exist or is not visible to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"operationId":"setAgentAccessManifest","tags":["Authenticated retrieval"],"summary":"Replace the access manifest for an agent principal (PREVIEW_NOT_LIVE).","description":"Appends a new manifest row in PREVIEW_NOT_LIVE state. Live agent execution requires a separate operator step to ACTIVE + FEATURE_P6_ARCI_MCP_LIVE=true.","security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"agent_id","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"201":{"description":"Manifest row created.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Request body or query failed schema validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource does not exist or is not visible to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/enterprise/accounts":{"get":{"operationId":"listEnterpriseAccounts","tags":["Authenticated retrieval"],"summary":"List enterprise accounts visible to the authenticated org.","description":"Visibility rule: the org is the enterprise_account.primary_org OR a workspace_org under it. Operator-onboarded only at this slice. No live SSO/SCIM/external-governance transport.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Array of enterprise accounts + capability state.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/enterprise/workspaces":{"get":{"operationId":"listEnterpriseWorkspaces","tags":["Authenticated retrieval"],"summary":"List enterprise workspaces visible to the authenticated org.","description":"Optional ?enterprise_account_id filter. Cross-account queries return an empty list (no existence disclosure). Joined with seat allocations (budget / allocated / active).","security":[{"bearerAuth":[]}],"parameters":[{"in":"query","name":"enterprise_account_id","required":false,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Array of workspaces + capability state.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/providers/{slug}":{"get":{"operationId":"getProvider","tags":["Public discovery"],"summary":"Public provider profile.","description":"Returns the operator-curated public provider profile for the given slug. Fields returned: slug, display_name, blurb, verification_tier, links[], accepted_provider_terms[] (provider_slug + display_name + version + commercial_posture + terms_document_url + accepted_at). Never returns email, stripe IDs, raw acceptance receipts, revoked_reason, or internal verification notes. cache-control public, max-age=300.","security":[],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","minLength":2,"maxLength":64,"pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$"}}],"responses":{"200":{"description":"Provider profile object.","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"description":"Provider slug not found.","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/v1/meta/provider-terms":{"get":{"operationId":"listProviderTerms","tags":["Public discovery"],"summary":"Public registry of premium provider terms (P6-ARCI-2 P2).","description":"Returns non-superseded provider terms with provider_slug + display_name + version + sha256 doc hash + commercial_posture + machine_readable_defaults JSONB. PREVIEW today (operator-onboarded only). cache-control public, max-age=300.","security":[],"responses":{"200":{"description":"Provider terms array + capability state.","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/v1/seller/provider-terms/accept":{"post":{"operationId":"acceptProviderTerms","tags":["Seller"],"summary":"Accept a provider-terms version for the seller org.","description":"Records the acceptance as a `kind=terms_acceptance` receipt (sha256 document_hash) and inserts the acceptance row with FK to the receipt. Idempotent: repeated calls for the same (seller_org_id, provider_terms_id) return the prior acceptance row.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Existing acceptance (idempotent replay).","content":{"application/json":{"schema":{"type":"object"}}}},"201":{"description":"New acceptance row + receipt id.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Request body or query failed schema validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource does not exist or is not visible to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/seller/provider-terms/{id}/revoke":{"post":{"operationId":"revokeProviderTermsAcceptance","tags":["Seller"],"summary":"Revoke a seller's acceptance of a provider-terms row.","description":"Marks the acceptance as revoked with `revoked_at` + bounded `revoked_reason` (1..240 chars). The original `kind=terms_acceptance` receipt remains in the append-only chain as historical evidence. Already-revoked / cross-org / non-existent acceptance ids return 404 (no existence disclosure).","security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Revocation acknowledged.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Request body or query failed schema validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource does not exist or is not visible to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}