ELTA Amazon plugin 0.22.0
0.22.0 — listing image slots: add, remove and its undo (IMG-3)
Backend 0.32.1 vendors it. One plugin level and three Seller actions in the existing
amazon.seller.listings family; no contract or core change, and existing actions keep their bytes.
- Level
LISTING_IMAGE(parentLISTING): the entity is the slot attribute name (main_product_image_locator,other_product_image_locator_1..8), the parent the SKU. amazon.seller.add_listing_image(ADD on the listing, creates the slot,ListingImageAdd {slot, url}, HTTPS only): an empty slot is ACCEPTED after Amazon'sVALIDATION_PREVIEW; an occupied slot (MAIN included) refusesALREADY_EXISTS/IMAGE_SLOT_OCCUPIED(use Change listing details to replace it). Apply sends onepatchListingsItemop=addon/attributes/<slot>with[{media_location, marketplace_id}](RFC 6902addcreates an absent member;replacerequires it). No automatic undo (fidelity NONE): Amazon re-hosts the image, so ELTA cannot prove the slot still holds its upload; use Remove image.amazon.seller.remove_listing_image(REMOVE on the slot,ANY_WITH_SNAPSHOT, drift REFUSE): MAIN refusesPROTECTED_TARGET("Amazon needs a main image; replace it instead") before any request; an empty slot is NO_CHANGE. The snapshotListingImageSnapshot {slot, media_location}keeps Amazon's exact as-read URL bytes; the drift token covers only that slot's value. Apply sendsop=deletewith only the marketplace selector.amazon.seller.restore_listing_image(revert-only ADD, BEST_EFFORT, "Restores Amazon's copy; Amazon may re-process it") writes the snapshot back withop=add, and refusesALREADY_EXISTSwhen the slot is occupied again; it never overwrites.- Apply's final listing read re-checks the slot after ELTA's gate: an add or restore into a slot
filled since then refuses
ALREADY_EXISTS/IMAGE_SLOT_OCCUPIED, and a remove whose slot token no longer equals its gatedbase_version(changed or emptied) refusesBASE_CHANGED; neither sends a PATCH. A change between that read and the PATCH is not caught: Amazon has no conditional write, so this narrows the race and is not atomic. - A 5xx answer to any image patch is UNKNOWN (labelled, never resent); UNKNOWN adds and restores always reconcile UNKNOWN: an occupied slot (and Amazon's re-hosted URL) proves no writer, so a seller's image is never recorded as ELTA's created entity.
- Known gap (core): ELTA's conflict keys do not overlap a
LISTING_IMAGEref with aset_listing_attributeon the same slot attribute (different targets inChangeKey.overlaps), so only the apply-time re-read and drift tokens separate them. - Catalog: additions only (the level and three actions); authz digest unchanged (generation 5).
0.21.1 — A+ create sends a document language
Backend 0.31.1 vendors it. Amazon requires contentDocument.locale on createContentDocument;
0.21.0 always sent null, so every live A+ create was refused before anything was saved.
CreateAplusDocument.locale(optionalAplusLocale, Amazon'sLanguageTagpattern^[a-z]{2,}-[A-Z0-9]{2,}$, hyphen form such asen-USores-US; the underscore form that publish records report is refused). An unset locale is omitted from every dump, so stored creates keep their bytes and hashes.- Apply sends
locale, else the marketplace's primary language fromAPLUS_MARKETPLACE_LOCALES(US en-US, CA en-CA, MX es-MX, BR pt-BR, UK en-GB, DE de-DE, FR fr-FR, IT it-IT, ES es-ES, NL nl-NL, SE sv-SE, PL pl-PL, TR tr-TR, IN en-IN, AU en-AU, SG en-SG, JP ja-JP). Multi-language or unverified marketplaces (BE, IE, ZA, EG, SA, AE) are absent: an unset locale there refuses the row in preview and apply before any request (PROVIDER_VALIDATION,/localeLOCALE_REQUIRED), never sending null. - The create preview and outcome label is
<name> (<locale>), so the approval shows the language even when it is the default; the undo target's label stays the bare name. - Catalog adds only the optional
localeproperty; no authz change. Rollback floor: a stored create with a setlocalecannot decode on 0.21.0.
0.21.0 — A+ writes are submitted for review; real A+ documents edit losslessly; A+ create undo
Backend 0.31.0 vendors it. Three changes ship together: every A+ write is submitted for Amazon review, the A+ read projects real documents typed so a SET resends them without loss, and an A+ create can be undone by unlinking all its products (Amazon keeps the document).
Real A+ documents read typed and round-trip
- One
AplusModuleProjection.to_providerowns both the SET wire body and the read/SET-current round-trip guard. A module is typed only when its round trip equals the normalized provider JSON; otherwise it stays the opaque{module_type, raw, supported: false}marker (for example aSTANDARD_COMPANY_LOGOwithcompanyLogo: null). Every body leaf (body,block.body, ...) is written as atextListparagraph, and a path the generated module model does not declare is refused rather than sent as an extra. AplusImageField.crop(AplusImageCrop {size, offset?}ofAplusImageLength {value, units}) carries Amazon'simageCropSpecification: read as-is and written back byte-identical. An unset crop or offset is omitted from every dump, so pre-crop proposals keep their bytes, hashes andmodel_version.- An undecorated empty text component in a declared optional
TextComponentproperty of a known module type (liveheadline: {"value": "", "decoratorSet": []}) reads as absent and a SET omits it, because Amazon's schema requiresvalueminLength 1. Any other{value: ""}field keeps the module opaque. Required body text keepsmin_length=1; an empty body row or decorated empty headline stays opaque. - Exact-key
aplus_documentsreads wrap each typed module asAplusReadModule {module, images};imagesholds one read-onlyAplusImagePreview {name, preview_url}per image field.preview_urlis set only foraplus-media-library-service-media/<id>.(jpg|jpeg|png|gif)asset IDs and is never part of a write model, hash or SET version. - Conversion runs inside the existing module-shape problem boundary for lookup and SET preview
reads: a SET preview whose current document has a module the typed SET cannot rebuild exactly
returns the existing
MALFORMED_RESPONSEissue instead of a lossy undo value, and never raises.
A+ writes are submitted for Amazon review
Every A+ write now ends with one postContentDocumentApprovalSubmission
(POST /aplus/2020-11-01/contentDocuments/{key}/approvalSubmissions?marketplaceId=…).
APPLIED = saved and submitted for Amazon review (async: SUBMITTED → APPROVED/REJECTED via
aplus_documents status); with no ASIN, create saves a draft only.
create_aplus_document: create → relations → submission. Amazon needs one or more ASINs before submission (create-edit-publish-aplus-content, Prerequisites), so a create with no ASIN is APPLIED with the label<name>: saved as draft; attach a product to submit for review.set_aplus_content: update → submission. Its BEST_EFFORT undo runs the same apply, so it resubmits too.set_aplus_asins: relations → submission for a non-empty set, because posting relations resets an approved document to DRAFT and Amazon says to submit again (a-plus-troubleshooting, "An approved document went back to DRAFT"); the empty detach set submits nothing.- A submission that fails after a successful write (non-2xx, transport error, timeout, or an
unreadable 2xx body) is UNKNOWN with the label
<name or key>: content saved, but the review submission is unconfirmed; check status in Seller Central, or edit and re-file. The content is written exactly once and nothing is resent.
The DRAFT/equal-content "submit only" retry is deferred: an unchanged SET still previews as
NO_CHANGE. The submission is behaviour only: no gate, comparison, current/version, stored-shape
or contract change; its only catalog change is the three A+ action changeSchema.description
texts.
A+ create undo unlinks all products; Amazon keeps the document
create_aplus_document now has an undo, the revert-only REMOVE detach_aplus_document
(ELTA_CREATED, REFUSE). Amazon cannot delete A+ content, so undo posts the empty ASIN set
(no submission), re-reads it to prove it empty, and the document stays in the account. Create is
EXACT (the contract's fidelity for a revertible ADD) with a revert note saying so. An APPLIED
create records created_version, the token of its sorted ASIN set; once the seller links other
products the undo refuses CHANGED_SINCE_APPLY, and a draft with nothing linked is NO_CHANGE.
An unlink whose re-read still shows products is UNKNOWN and never resent; so is an unlink answered
by a 5xx, transport error, timeout or unreadable body, because it may have landed (only a 4xx
refusal is REJECTED). A relation page missing Amazon's required asinMetadataSet or a row's
asin is MALFORMED_RESPONSE, never an empty set, so it cannot bypass the changed-ASIN guard
or falsely confirm an unlink. The undo reads only the relations and names the document from the
created target's label (older targets show the document key), so no module content can block it.
Direct proposals of the detach refuse REVERT_ONLY.
Creates stored before 0.31.0 or reconciled from UNKNOWN carry no created_version, so their
undo is guarded only by the preview's product count and REFUSE drift.
Catalog for 0.21.0: the three descriptions above, the crop leaves under the create/SET change
schemas, the crop/preview/read-module leaves under the aplus_documents result schema, the new
detach_aplus_document action, and create's fidelity (EXACT), revertActionKey and
revertNote. A stored proposal that carries a crop or a detach cannot decode on 0.20.0
(extra-forbid / unknown action), so once one is stored the rollback floor is backend 0.31.0.
The detach reuses family amazon.seller.aplus, so the authz manifest is unchanged by it.
0.20.0 — an UNKNOWN keyword ADD reconciles by its natural key
amazon.ads.add_keyword and amazon.ads.add_negative_keyword reconcile an UNKNOWN send once
from the natural key apply reports: the ad group plus the exact, case-sensitive keyword text and
match type, listed with adGroupIdFilter, keywordTextFilter (EXACT_MATCH), matchTypeFilter
and stateFilter ENABLED/PAUSED only. Exactly one live match returns its provider keyword id as
created, so archive_keyword passes the ELTA-created gate; zero, several, a case variant, an
archived-only row or a failed read stays UNKNOWN. A duplicate positive keyword ADD now previews
as NO_CHANGE when an equal ENABLED/PAUSED row exists, so that create is never sent, while an
archived equal row still allows a fresh ADD. No action, family, declaration, catalog or
stored-byte change: the two ADDs still declare no created_from.
0.19.0 — current listing and bounded published A+ facts on previews
The four listing actions declare ListingTargetFacts: current is the unchanged snake_case
ListingCurrentFacts projection already returned by listing_items, from the same listing read.
Every row whose target read obtained that listing retains its facts even when validation, a prior
value or inventory check refuses it. A row without a successful listing read never fabricates facts.
aplus performs one contentPublishRecords page read per SKU's own-summary ASIN, retaining only
that account's marketplace. Its state is PUBLISHED for an observed matching reference,
NOT_PUBLISHED only for an exhausted page with none (a draft may still exist), or UNREAD for an
empty continuation, missing ASIN or failed/skipped read. records keeps only reference key, raw
content type and locale. No metadata, workflow status, draft scan or ASIN relation read; A+ failure
cannot reject the listing preview or discard current. Same-SKU attribute rows share the read.
A no-try boundary records transport, built-in timeout and payload failures as UNREAD, warning with
only the exception type; unexpected defects and cancellations propagate without hiding them.
Facts describe preview-time observations and refresh on re-preview. They are display-only, separate from the write's current value, version, undo baseline and approval/replay hashes.
Repins plugin-contract >=0.16.0,<0.17; ship with backend 0.29.0 after BE readers accept contract
4.5.0. No action key, family, permission or authz-generation change.
0.18.1 — a refused listing row still names the product
A SET_LISTING_ATTRIBUTE row whose shared VALIDATION_PREVIEW returns a provider issue became
present=False with the issue and no display, so the change-list preview showed a nameless,
imageless row although the same request had already read the listing. The listing_display
projection is now taken once from that read and kept on every issue state the same method
returns: the failed validation, the listing that omitted its product type, and the row whose
prior attribute is missing. No extra provider call, contract or change-schema field: label
and image_url already existed on TargetState and stay display-only, outside versions and
hashes. Stored previews keep their bytes.
0.18.0 — current A+ content and typed listing reads
amazon.seller.aplus_documents exact-key reads now include ordered current modules, content type,
locale, update time and badges. The shared GET sends includedDataSet=CONTENTS,METADATA as one CSV
parameter, including SET content previews. Supported modules reuse the existing write converter;
unknown or unsupported modules remain read-only {module_type, raw: true, supported: false}
markers, so they cannot hide the rest of the document. Lookup-only envelopes accept raw Amazon
content types EBC (Seller Central A+), EMC (Vendor Central A+), BrandStory and future values.
Generated models are not edited; strict write models and write acceptance remain unchanged.
The existing asin query now uses contentPublishRecords, not an all-document relation scan.
It finds published documents only; drafts remain reachable by exact name or reference key.
All A+ metadata/relation/publish continuations send Amazon's pageToken alone, as required.
ASIN/name pages omit module content; a matched reference supplies live metadata and current ASIN
relations. rejection_reasons is removed: Amazon exposes workflow status and badges, not document
rejection explanations. Those explanations must be checked in Seller Central.
A+ image modules still expose uploaded asset references, not guessed URLs. getMedia can return a
mediaUrl for a known mediaId, but this model supplies no read-only mapping from an image module's
uploadDestinationId to that mediaId. The documented resolver is the mutating createMedia POST;
no media lookup or mutation is added. ASIN-relation eligibility validation remains a follow-up.
amazon.seller.listing_items adds optional typed current from the same provider response while
retaining all raw groups. It includes marketplace-language text, ordered bullets, HTTPS image
slots, a current B2C amount/currency and minimal product attributes. Marketplace-scoped values win
then unscoped values; scalar values use the first applicable row, with no translation. Price is
None if the exact-marketplace B2C offer is missing or ambiguous; no B2B or scheduled-price fallback.
No action/family key, permission, authz generation, hash algorithm or stored write schema changes. The corrected A+ dataset request can change newly observed SET content versions when Amazon now includes metadata/content; existing proposals retain their stored preview/hash bytes. Listing display helpers are shared without changing their existing write-side selection or versions.
0.17.2 — Ads accounts name their country
One advertiser's per-country Ads profiles share one name, so every choice read "Asiboan". Ads
discovery now titles a profile "name · country" ("Asiboan · US") with the same
elta_amz.regions.account_title rule as Seller's "store · marketplace" ("Asiboan · Amazon.com").
The plugin holds no marketplace-name table, so Ads uses the profile's country code; a profile
without one keeps its name. Titles are display only and enter no hash, version or identity.
A stored connection keeps its old titles until it is rediscovered: a capture request
("sync now"), a reconnect, or a changed permission declaration.
0.17.1 — new and restored listing rows show the product
add_listing and restore_listing previews target a SKU that does not exist yet, so they used
to label the row with the SKU only. They now take the row's own item_name (this marketplace's
entry, else the unscoped one; SKU fallback) and, for a create, its MAIN image URL; a restore
snapshot keeps no images, so it shows none. Their marketplace-mismatch refusals show the same.
SET and REMOVE rows already carried the live title and image since 0.16.0. The label is part of
the preview hash, so only newly read create and restore previews hash differently; a stored
proposal re-hashes from its stored previews. No action, change schema or refusal key changed.
0.17.0 — FBA placement and carrier confirms, committed-plan cancel, shipment labels
BL-16 finishes the FBA inbound steps after packing, behind the new default-off
amazon.seller.fba_inbound_shipments family: these three calls charge the seller, so a store with
the fee-free amazon.seller.fba_inbound_plans switch on never gains them.
amazon.seller.confirm_fba_placement is an ADD of the plan's one placement option
(created_from the option id): an identical resend once it is accepted is NO_CHANGE, a
different option after confirmation is WINDOW_CLOSED, and Amazon offers no undo.
amazon.seller.confirm_fba_transportation is an ADD of one carrier per shipment
(selections) plus one top-level private freight contact for pallets, quoted with the carrier cost
and the void deadline Amazon returns only after the confirm; the contact is copied into every
selection at apply and never lives under an array item. amazon.seller.cancel_confirmed_fba_inbound_plan
is the REMOVE that voids a committed plan, a forward filing in the same charged family whose read
allows it only inside Amazon's window. Both confirms refuse on drift; the cancel applies anyway.
The same release adds three lookups: amazon.seller.fba_placement_options (a plan's options with
their shipment split, placement fees, discounts, expiry and one options_version, generating free
on the first page while no unexpired option is offered or accepted), amazon.seller.fba_transportation_options
(one placement's options per shipment with carrier, mode, quoted cost and expiry, generating only
with a configuration and never once transport is confirmed) and amazon.seller.fba_shipment_documents
(box labels, pallet labels or bill of lading with READY and a short-lived link,
AWAITING_PLACEMENT/AWAITING_TRANSPORT, or NOT_APPLICABLE without pallets; the link expires in
seconds and is never stored). The levels INBOUND_PLACEMENT and INBOUND_TRANSPORT join
INBOUND_PLAN, the inbound plan status reading gains accepted_placement_option_id and
shipments, and two issue codes are new: PLACEMENT_OPTION_NOT_FOUND and
INBOUND_SHIPMENT_NOT_FOUND. No new refusal key. The floor is 0.25.1 for every record stored
today and 0.26.0 once a proposal holding one of the three new action keys is stored, because
0.16.1 refuses that row with UnknownKey.
0.16.1 — the packing preview returns Amazon's current, so the core SET gate accepts it
amazon.seller.set_fba_inbound_packing is a SET whose target read returned presence without a
current, so the core gate refused every packing row as REQUEST_REJECTED. The read now returns
the typed current: the ACCEPTED packing option's id, else none, plus the saved boxes from
listPackingGroupBoxes in the option's packingGroups order, mapped into the request's own
FbaPackingBox shape. An identical resend is NO_CHANGE; nothing saved yet gives the empty
SetFbaInboundPacking(), accepted as a new change. A saved box missing a usable field keeps the
option and claims no boxes, so it can only cause a resend, never a false NO_CHANGE. The current
admits that empty shape, so the change schema widens: packing_option_id is optional and
groupings may be empty. A request in that shape is refused as PROVIDER_VALIDATION at preview
and at apply, before any read or write. Quote and version are computed from the same inputs and
are unchanged. No new kind, family or refusal key. The rollback floor stays 0.25.0 for every
record stored today, but a filed packing proposal keeps the empty current in its preview
(packing_option_id: null, groupings: []), which 0.16.0 refuses: never roll ELTA below 0.25.1
once such a proposal is stored.
0.16.0 — change rows show the product; a create never attaches to an existing ASIN; product ads pause
Listing change rows (SET and REMOVE, including their refusals) are labelled with the listing's
full itemName, falling back to the SKU, and carry the main image (mainImage, then the
marketplace's main_product_image_locator); A+ rows are labelled with the document name. The
label is part of the hashed preview, as the SKU was before, so a new proposal hashes the title;
stored proposals verify against their own stored previews. CreateListing refuses ASIN-binding
rows (merchant_suggested_asin, an ASIN identifier, legacy external_product_id_type=ASIN) as
IDENTITY_ATTRIBUTE before any provider call, and a GTIN-family row that searchCatalogItems
matches in the target marketplace as CATALOG_MATCH; the check runs at preview and again at
apply. New amazon.ads.set_product_ad_state (SET_STATE at AD, SP only) pauses or enables one SP
product ad behind its own default-off amazon.ads.product_ad_state family; EXACT undo, applies
over drift. No new refusal key or change class; the live product-ad route is fixture-proven only.
0.15.2 — the listing lookup explains its own edit time
amazon.seller.listing_items now declares its meaning: it reads the requested SKUs from
Seller Central at request time with their summaries, attributes, issues and offers, and a
summary's lastUpdatedDate is when the seller last edited the listing, not when it was read.
The plugin owns that fact, so a consumer no longer restates it in its own guidance; every other
Amazon lookup stays without one. Repins plugin-contract >=0.14.4,<0.15, which refuses blank,
multi-line or dotted-key guidance at registration. No provider call, capture, write or runtime
backend pin changes.
0.15.1 — repins plugin-contract 0.14.0
Repins plugin-contract 0.14.0 (>=0.14,<0.15), which lets a Source declare its removal reach
and revoke page. Amazon declares neither, so its removal stays LOCAL without a URL: Amazon Ads is
region-specific and Seller Central is per marketplace, and a wrong link would be worse than none.
No declaration, provider call, capture, lookup or write changed.
0.15.0 — Ads money writes refuse a moved value, and an unknown MSKU is the caller's
The three Ads money writes amazon.ads.set_target_bid, set_campaign_budget and
set_ad_group_bid now carry DriftPolicy.REFUSE, and their readers record the live bid or daily
budget as the version token, so an apply whose value moved after the preview refuses with
BASE_CHANGED instead of overwriting it. Amazon Ads has no conditional write, so the re-read just
before sending is the boundary. An Ads bid or budget proposal saved before 0.19.0 and approved
after it has those rows refused with BASE_CHANGED; propose it again.
amazon.seller.fba_prep_details answers Amazon's refusal of a batch that
names an MSKU it does not know as NOT_FOUND with Amazon's own line, so the caller checks the
MSKU instead of reading REQUEST_REJECTED with SUPPORT.
0.14.2 — A+ field shape and prep-details MSKUs
The A+ content preview now refuses a text field that does not fit Amazon's module shape, such as
body.textList on STANDARD_TEXT, with PROVIDER_VALIDATION at /content/modules/<i> instead
of failing the read, because the caller's own field name is theirs to fix and never a provider
outage.
listPrepDetails sends one comma-joined mskus value per 100-MSKU batch. Amazon reads only the
first of repeated parameters, so the amazon.seller.fba_prep_details lookup and the FBA create
preview now read every requested MSKU rather than the first of each batch, with each MSKU's own
%, + and , still double-encoded. No wire change.
0.14.1 — accepted placement and never-stocked FBA inventory
Amazon reports an accepted FBA placement option as ACCEPTED, so the FBA cancel check and the
amazon.seller.fba_inbound_plan_status lookup's committed now count it. Before, the check
looked for CONFIRMED, a value Amazon never returns, so only selected transportation or a
shipped shipment closed the window.
The FBA inventory read behind the amazon.seller.fba_inventory lookup and the remove-listing
check now reads only each summary's SKU and quantities, so a summary with an unusable
last-updated time, as Amazon sent for an SKU that never held stock, no longer fails the read.
A malformed quantity still fails it, because those totals gate the removal refusal. No wire
change.
0.14.0 — FBA prep details, honest preview, Amazon's failure message
The new read-only amazon.seller.fba_prep_details lookup reads Amazon's saved prep details for
1 to 100 exact MSKUs (1-255 characters each). Rows carry Amazon's own strings, and Amazon omits
an MSKU it does not know and prep entered only in Seller Central, so a missing row says nothing
about the item.
The create preview refuses the Brazil account before any read, and otherwise refuses an item only when it breaks an explicit prep-owner or label-owner constraint, or when a MUST_MATCH all-owners constraint meets two different owners. A missing row and an UNKNOWN category pass, because Amazon states its own constraints and validates the rest at apply. A failed FBA operation now shows Amazon's own message first, with its details in parentheses.
amazon.ads declares no operator app renewal row: the shared public Ads app has no expiry, so
ELTA_OAUTH_APP_SECRET_ROTATED_AT is retired and ignored if still set. Token refresh and the
365-day customer consent clock are unchanged, and the Seller public app keeps its 180-day row.
0.13.0 — keyword write family and inbound plan history
Positive keyword writes leave the negative-keywords switch. The new amazon.ads.keywords family
("Add and remove keywords") allows add_keyword and archive_keyword; the existing
amazon.ads.negative_keywords family keeps its key for saved policies and is retitled "Add and
remove negative keywords", so one switch no longer allows both kinds. Store owners must enable
the new switch to keep positive keyword adds.
Three read-only lookups read earlier FBA inbound plans: amazon.seller.fba_inbound_plans lists
the bound marketplace's plans (status filter, last-update or creation order, 30 per page) and
amazon.seller.fba_inbound_plan_items/amazon.seller.fba_inbound_plan_boxes read one plan's
MSKU lines and packed boxes (up to 500 per page; an unknown plan is INBOUND_PLAN_NOT_FOUND).
Amazon's plan filter can leave a page short or empty while a cursor is returned, so an agent
keeps paging. The plan's ship-from address is never returned. The listing and A+ undo notes now
address the seller instead of naming ELTA; no action behavior, key or hash changed.
0.12.1 — Ads consent renewal deadline
amazon.ads declares consent_lifetime_days=365, so existing connection projections show
renewal from the latest successful consent (legacy grants fall back to first bind). Amazon's
https://advertising.amazon.com/API/docs/en-us/guides/get-started/retrieve-access-token
states that refresh tokens issued on or after July 30, 2026 expire 365 days after advertiser
consent; earlier tokens have no fixed expiration and receive a conservative renewal prompt.
Token refresh does not restart this clock. No plugin-contract or wire schema changes.
0.12.0 — Seller consent style
Pins plugin-contract >=0.13.0,<0.14. amazon.seller now offers the website-authorization
CONSENT way beside the seller's own private app, but only once the operator configures the
client's public SP-API app; otherwise connect stays {CREDENTIALS} and the source stays
available (never available=False).
start returns one Seller Central site per Amazon store of the store's region (23 stores, each
with a bilingual country label), all sharing one 600-second round state, with url set to the
first site for clients predating site selection. exchange requires the callback's selling
partner id (Amazon's selling_partner_id, forwarded neutrally as callback_account_id) and
returns a grant sealing only refresh_token, access_token and selling_partner_id; a missing
or blank id is a typed reconnect. refresh uses the app that issued the grant: the seller's
sealed private pair for a credentials grant, otherwise ELTA's operator public app, keeping the
selling partner id either way. A consent grant declares consent_lifetime_days = 365 (Amazon's
reauthorization rule), selected by bound_with instead of the private secret's 180 days. With no
seller-owned secret to name, an expired operator public secret classifies as
REQUEST_REJECTED/SUPPORT, never a customer reconnect. ELTA_SELLER_PUBLIC_APP_SECRET_ROTATED_AT
tracks the public pair through the operator renewal path; the shared Ads pair declares no
renewal row (0.14.0).
0.11.0 — LWA secret lifecycle
Pins plugin-contract >=0.12.1,<0.13. Seller client secrets declare a 180-day lifetime and
bilingual renewal steps: rotate in Seller Central, allow up to about 15 minutes for Amazon
to propagate the new secret, then update it. A 403 whose details say the secret expired becomes
AUTH_INVALID naming the seller's secret; role denials still name the missing permission.
Seller LWA invalid_client also names the secret, and A+ upload preserves this issue. The report
fatal-detail fallback remains PROVIDER_UNAVAILABLE so the next createReport classifies it;
MCF reconciliation deliberately retains UNKNOWN to avoid claiming a write's outcome.
The operator-owned Ads pair declares no renewal row: the shared public Ads app has no expiry,
so ELTA_OAUTH_APP_SECRET_ROTATED_AT is retired and ignored if still set, and no date is
inferred from import history. Token refresh is unchanged: ELTA refreshes on demand within five
minutes of expiry and re-seals a rotated token. Rotation must still update the secret in every
ELTA2 Infisical scope holding the pair (hk-services prod / and test-shared prod /elta2);
config-roll all three services in each environment. hzads ELTA1 updates its own stored pair through its own path and has no rotated-at
setting. With no customer-owned secret to name, an expired operator secret is REQUEST_REJECTED
(SUPPORT), never a customer reconnect instruction.
Amazon Ads hosts follow the store's sales region: consent uses that region's LWA prefix and the token exchange uses that region's LWA token host, so an EU or FE advertiser signs into its own Amazon account system instead of an amazon.com account that may hold no advertising access.
0.10.0 — Amazon's own levels, refusals and MCF quote choice
Declares Amazon's vocabulary under plugin-contract 0.12.0: the seven entity levels no other provider
has (AmazonLevel) and the five provider-only refusal codes, each naming the standard target reason
it is a case of, so PLACEMENT, PURCHASED_PRODUCT and the rest leave the shared contract. The MCF
create action gains quote_choice, and the reader-less fba_inbound_plans and mcf_orders datasets
with their three families move to retired for the operator retirement run. exchange() drops
selling_partner_id and presence_reconcile is called through the protocol. Stored keys, action
keys and approval hashes are unchanged; the pin becomes >=0.12,<0.13.
Private address text now reparses ELTA's retention token without weakening ordinary provider bounds or changing schemas.
0.9.2 — keyword ADDs send the parent campaign id
amazon.ads.add_keyword and amazon.ads.add_negative_keyword now resolve the target ad group's
parent campaignId through the same SP ad-group read the ADD preview already uses and send it in
the create body. Amazon SP v3 requires both adGroupId and campaignId, so the two actions
previously previewed as accepted but were refused at apply with HTTP 400 INVALID_ARGUMENT
("Value null at 'keywords.1.member.campaignId'") and wrote nothing. A missing or uneditable
parent now returns the preview's typed prerequisite issue instead of a provider failure. No
wire-contract change: plugin-contract stays 0.11.0.
0.9.1 — FBA source address is required in its change schema
amazon.seller.create_fba_inbound_plan now declares source_address.city and
source_address.phone_number required in its change schema, matching the validator it
already had and SP-API v2024-03-20 AddressInput. The typed FbaSourceAddress owns that
rule, so the rule is no longer duplicated in an after-validator. Requests without either
field were already refused with 422, so no previously accepted request changes; the shared
MCF destination address keeps both optional.
0.9.0 — ELTA 3.5 provider cut
Repins plugin-contract 0.11.0, adopts localized declarations and standard ad metrics, and validates schema-generated dataset payloads. Adds live Seller status/product-type reads, retires reader-less capture declarations and returns typed resource-not-found issues. Regional routing and approved-write identity remain intact; live provider acceptance is separate from this packages-only cut.
0.8.0 — neutral Ads intents
Repins plugin-contract 0.10.0, declares seven neutral intents, and adds SP campaign pause/enable plus ad-group default bids. Campaign state is a separate default-off switch; stored subclass names, action keys and approval hashes stay unchanged. Ship with the ELTA 3.4.0 paired contract/client/backend consumer train.
elta-amz is the Amazon provider plugin for ELTA. It implements
elta_plugin_contract only and owns every Amazon-specific fact: the declaration
(Amazon Ads + Seller Central sources, 18 capturing Ads datasets - 15 ordinary daily
reports plus 3 UNVERIFIED gross-and-invalids - and settings, families,
measures and metrics), LWA consent and refresh, report reads, report mapping and
the metric formulas, including TACOS.
ELTA core owns storage, timing and history; it never imports this package. The
plugin never imports ELTA core or arch/.
Centralized Ads mutations
AdsActions.read_targets reads Sponsored Products settings for the declared writes.
It reports current values, labels, presence and typed provider issues; ELTA core owns
policy, re-gating, diffs and pre-write records. AdsActions.apply sends only approved
writes and never compares with an earlier preview. Amazon has no conditional writes,
so a provider-side race remains after ELTA's final read. Keyword creation returns its
provider id only when confirmed, authorizing the declared archive inverse.
| Action key | Neutral intent / target level | Store switch | Refresh |
|---|---|---|---|
amazon.ads.set_target_bid |
SET_BID / TARGET | BIDS | SP keyword and target settings |
amazon.ads.set_target_state |
SET_STATE / TARGET | BIDS | SP keyword and target settings |
amazon.ads.set_campaign_budget |
SET_DAILY_BUDGET / CAMPAIGN | BUDGETS | SP campaign settings |
amazon.ads.set_campaign_state |
SET_STATE / CAMPAIGN | CAMPAIGN_STATE | SP campaign settings |
amazon.ads.set_ad_group_bid |
SET_BID / AD_GROUP | BIDS | SP ad-group settings |
amazon.ads.set_product_ad_state |
SET_STATE / AD | PRODUCT_AD_STATE | SP product-ad settings |
amazon.ads.add_keyword |
ADD_KEYWORD / AD_GROUP | KEYWORDS | none |
amazon.ads.archive_keyword |
none / TARGET | KEYWORDS | none |
amazon.ads.add_negative_keyword |
ADD_NEGATIVE_KEYWORD / AD_GROUP | NEGATIVES | none |
amazon.ads.archive_negative_keyword |
none / TARGET | NEGATIVES | none |
Keyword writes have one switch each. The new amazon.ads.keywords family ("Add and remove
keywords") allows add_keyword and archive_keyword only; the existing
amazon.ads.negative_keywords family keeps its key for saved policies and is retitled
"Add and remove negative keywords", so it now allows the two negative actions only.
Campaign state has the new amazon.ads.campaign_state family, off by default;
existing enabled bid/budget families never authorize it. BIDS keeps amazon.ads.bids
and explicitly includes the ad-group default bid. Campaign pause/enable uses
PUT /sp/campaigns with state; ad-group bids use PUT /sp/adGroups with numeric
defaultBid. Both have EXACT undo by restoring the live before-value: a state toggle
applies over drift, while the ad-group default bid refuses a live bid that moved after the
preview. An SB/SD or unknown id misses the SP settings list and is NOT_FOUND at preview;
archived entities retain the existing typed lifecycle issue.
Product-ad pause/enable (CG-ADS-PAUSE-1) follows the same campaign-state pattern with its own
amazon.ads.product_ad_state family ("Pause or enable product ads"), off by default: it
reads POST /sp/productAds/list for the before-state and sends PUT /sp/productAds with
{"productAds": [{"adId", "state"}]}. It is SP only; an SD product ad misses the SP list and
is NOT_FOUND. No provider writes are performed by the fixture tests; Asiboan live acceptance remains a later gated step.
ELTA owns the neutral change bases. Amazon retains SetBid, SetDailyBudget,
SetTargetState, AddKeyword and AddNegativeKeyword as subclasses because stored
outcomes name those concrete types. Field names and approval hashes stay unchanged.
TargetEnablement aliases neutral EntityState; positive keywords use
KeywordMatchType.EXACT (the former PositiveMatchType is removed). Amazon's
AddKeyword still requires a positive 12-digit/2dp bid; unlike the neutral base it
never admits an omitted or null bid. Later SB/SD support extends these same keys and
dispatches per ad product, rather than declaring competing intent/level actions.
Version 0.6.0 adds the Wave M Seller action schemas and four live lookup handles, all
re-exported from the package root. Seller lookups now include Catalog Items by ASIN,
Listings Items by SKU, A+ documents by ASIN/name/content reference, FBA packing options by
inbound plan, and live FBA inventory by seller SKU. Every lookup uses the supplied account's
region and marketplace with the existing Seller permission; results are returned live and are
not persisted. The listing, A+, packing-option and inventory HTTP reads are shared with their
existing Seller action paths. The public A+ response schema exposes workflow status but no
rejection-reason field, so rejection_reasons remains empty. The vendored
elta-plugin-contract (>=0.12,<0.13) validates action fidelity/drift metadata.
Product type lookups (additive): amazon.seller.product_type_search searches the bound
marketplace by keywords or item name, and amazon.seller.product_type_definition reads the
seller-specific Product Type Definition (sellerId from the grant). Its JSON Schema body is
fetched only from Amazon's returned schema.link.resource through fetch_guarded (JSON only,
20 MB, 15 s); schema_sha256 is the SHA-256 of those exact bytes. An unknown type returns
PRODUCT_TYPE_NOT_FOUND; a guard refusal returns a typed issue with the refusal code.
Inbound plan status lookup (additive): amazon.seller.fba_inbound_plan_status reads one plan
through the GETs the FBA actions use and returns Amazon's free-string status unchanged (documented:
ACTIVE, VOIDED, SHIPPED, ERRORED; newer values pass through), committed (placement confirmed, transportation selected or shipped) and the
accepted packing option from the plan's own summaries. An unknown id returns
INBOUND_PLAN_NOT_FOUND. amazon.seller.mcf_order_status reads one seller order through
getFulfillmentOrder and returns its existing typed status. Both reads use the bound
account's regional host. These are live reads, not capture-day or apply-success claims.
The reader-less amazon.seller.fba_inbound_plans and amazon.seller.mcf_orders datasets
and their three fact families are removed. No action refreshes them. Existing empty
lane/coverage metadata has a bounded dry-run-first operator cleanup in the backend;
it never deletes stored facts and refuses if a retired family contains any.
LISTING_NOT_FOUND, APLUS_DOCUMENT_NOT_FOUND, INBOUND_PLAN_NOT_FOUND and
PRODUCT_TYPE_NOT_FOUND now mean NOT_FOUND / CHECK_REQUEST, keeping their provider detail.
Amazon Ads state dimensions use uppercase spellings across older/newer API payloads.
Inbound plan history (additive): amazon.seller.fba_inbound_plans lists the bound
marketplace's plans, filterable by ACTIVE/VOIDED/SHIPPED, ordered by last update or
creation in ASC/DESC order, at most 30 per page. Amazon's own filter can leave a page short
or empty while a next cursor is still returned, so an agent keeps paging until no cursor
comes back. The plan's ship-from address is never returned.
amazon.seller.fba_inbound_plan_items reads one plan's MSKU lines (identity, quantity, label
and prep owners, expiration and lot code) and amazon.seller.fba_inbound_plan_boxes its
packed boxes (contents, dimensions, weight, content source and template name), up to 500 per
page; an unknown plan returns INBOUND_PLAN_NOT_FOUND. All three use the FBA inventory
permission of fba_inbound_plan_status on the bound account's regional host.
FBA prep details (additive): amazon.seller.fba_prep_details reads the bound marketplace's
saved prep details for 1 to 100 exact MSKUs (1-255 characters each, as mskus) and returns,
per MSKU, Amazon's own strings: the prep category, the prep types and the prep-owner,
label-owner and all-owners constraints. Amazon refuses a batch that names an MSKU it does not
know (400 "The following MSKUs are not valid: [...]"), which ELTA answers as NOT_FOUND with
Amazon's own line, so the caller checks the MSKU; prep entered only in Seller Central is not
returned, so a missing row only means Amazon returned nothing for that MSKU. Reads use the FBA
inventory permission of fba_inbound_plan_status on the bound account's regional host, 100
MSKUs per request with 0.5 s between batches (Amazon's 2 requests/s), and persist nothing.
FBA placement, transport and documents (BL-16, additive, never on snapshots):
amazon.seller.fba_placement_options and amazon.seller.fba_transportation_options read every
Amazon page and answer the whole option set on the first page, each row carrying one
options_version (sha256 of the set, live_reads.placement_options_version /
transportation_options_version, which the confirm reads reuse). Only the first page generates
(free): placement when no unexpired option is OFFERED or ACCEPTED, transport when the query has a
configuration (ready-to-ship start, plus pallets and freight per shipment) and no shipment has a
selected transport yet. Generation polls about 20 s inside the 30 s client bound; still running
is a retryable PROVIDER_UNAVAILABLE. amazon.seller.fba_shipment_documents decides READY,
AWAITING_PLACEMENT, AWAITING_TRANSPORT or NOT_APPLICABLE (no pallets) from getShipment, then
mints v0 box labels (UNIQUE, every box id), pallet labels (PALLET, the pallet count) or the bill of
lading on the confirmation id; the ~15 s link is a result field only, never stored.
fba_inbound_plan_status adds the accepted placement and each listed shipment (confirmation id,
status, warehouse, selected transport) from the same single getShipment pass committed uses.
FBA placement and transport writes (BL-16) sit in their own family
amazon.seller.fba_inbound_shipments ("Confirm or cancel FBA shipments (Amazon fees apply)"),
off by default, so the fee-free fba_inbound_plans switch never grants them.
amazon.seller.confirm_fba_placement and amazon.seller.confirm_fba_transportation are ADDs at
INBOUND_PLAN that create INBOUND_PLACEMENT / INBOUND_TRANSPORT from placement_option_id,
quoted, NONE undo, drift REFUSE on the lookup's options_version. Their reads only list:
the same confirmed choice is NO_CHANGE, a different one is WINDOW_CLOSED, and transport needs
the placement ACCEPTED, one partnered option per placement shipment, one mode (small parcel or
LTL), one carrier for small parcel, and the private top-level contact exactly for LTL (copied
into every selection at apply). A lost answer after send (5xx, no operation id, lost poll) is
UNKNOWN with no issue and reconciles from a fresh read; a FAILED operation re-reads Amazon, and a
mixed transport result is UNKNOWN with NOT_CONFIRMED per unmatched selection. The transport
APPLIED outcome re-lists the options once for carrier, cost and Amazon's voidable_until.
amazon.seller.cancel_confirmed_fba_inbound_plan (REMOVE, ELTA-created plans) cancels a
committed plan before transport or before the smallest void deadline, re-reading at apply;
otherwise WINDOW_CLOSED. All three are fixture-proven only.
The create preview reads the same details: it refuses a Brazil account before any read, and
otherwise refuses an item only when it breaks an explicit prep-owner or label-owner constraint
(field /items/<n>/prep_owner or /items/<n>/label_owner), or when a MUST_MATCH all-owners
constraint meets two different owners (field /items/<n>), each with PROVIDER_VALIDATION. A
missing row, an UNKNOWN category or a category without a constraint passes, because Amazon
states its own constraints and validates the rest at apply; an MSKU Amazon does not know
refuses the row with that NOT_FOUND answer before anything is sent. A failed FBA operation
reports Amazon's message first, with its details in parentheses, instead of the generic
resource template alone.
Layout and E1 unit ownership
| Path | Protocol | E1 unit |
|---|---|---|
src/elta_amz/declaration.py |
— (Amazon's declaration and its own AmazonLevel/AmazonRefusal keys) |
Ads and seller declarations, including W4.3 mutation actions and the Wave M types-only block |
src/elta_amz/plugin.py |
ProviderPlugin (handle-keyed dispatch) |
frozen |
src/elta_amz/lwa/client.py |
shared LWA login (LwaClient) |
Ads |
src/elta_amz/ads/authority.py |
ConnectionAuthority |
Ads |
src/elta_amz/ads/actions.py |
ProviderActions |
Ads W4.3 mutations |
src/elta_amz/ads/readers.py |
DatasetReader |
Ads |
src/elta_amz/ads/mappers.py |
FactMapper |
Ads |
src/elta_amz/ads/profiles.py |
profile discovery parse | Ads |
src/elta_amz/seller/authority.py |
ConnectionAuthority |
seller + TACOS |
src/elta_amz/seller/settings.py |
seller deployment settings (public app) | seller + TACOS |
src/elta_amz/seller/stores.py |
Seller Central consent sites | seller + TACOS |
src/elta_amz/seller/grant.py |
sealed grant shape and issuing app | seller + TACOS |
src/elta_amz/seller/readers.py |
DatasetReader |
seller + TACOS |
src/elta_amz/seller/mappers.py |
FactMapper |
seller + TACOS |
src/elta_amz/calculator/__init__.py |
MetricCalculator composer (written) |
frozen |
src/elta_amz/calculator/ads.py |
MetricCalculator |
Ads |
src/elta_amz/calculator/seller.py |
MetricCalculator |
seller + TACOS |
src/elta_amz/calculator/tacos.py |
MetricCalculator |
seller + TACOS |
src/elta_amz/_generated/ |
moved generated Ads + selling_partner + report_models clients | read-only |
scripts/build_spapi_spec.py |
upstream SP-API spec builder | Ads |
Every remaining stubbed method body is raise NotImplementedError("E1: <unit>").
The dispatcher and calculator composer remain handle-driven; Ads mutation declarations
and provider I/O are owned by the Ads source package.
Store regions
The core selects authority(source, region) before binding. Seller and Ads account
discovery use that region; Ads discovery excludes profiles from other sales regions.
The catalog advertises NA/EU/FE. Ads is unavailable when its operator app settings
are incomplete; Seller is always available, through the seller's own private app and,
when the operator configures the client's public app, through consent too. Ads readers and actions and Seller readers select NA/EU/FE API hosts from
AccountRef.region through elta_amz.regions, never deployment endpoint settings.
Opaque read handles retain that account region for later polling, downloads and pages;
old regionless handles cannot resume safely and are refused rather than defaulted to NA.
ELTA_ADS_API_BASE_URL and ELTA_SP_API_BASE_URL are no longer plugin settings.
Seller LWA tokens remain on api.amazon.com: SP-API explicitly documents that host for every
sales region. Ads consent and token hosts are region-keyed in elta_amz.regions (NA/EU/FE),
because each region's LWA prefix signs the advertiser into a different Amazon account system
(ADS_AUTHORIZATION_URLS, ADS_TOKEN_URLS). EU/FE routing is proven offline with recorded
request URLs; Ads consent and live capture/write acceptance remain unverified.
Seller binding: the seller's private app or public-app consent
Seller Central connects with four values from the seller's self-authorized private
SP-API app (CREDENTIALS): LWA client ID, LWA client secret, Refresh token, and
Seller ID (Merchant Token). The LWA client ID is not the Application ID.
The store-binding form sends these values to POST /v2/connections/credentials
(ConnectWithCredentialsRequest.store_id, .source_key and .fields); the
amazon.seller declaration owns the credential keys. The plugin trims values,
uppercases the Seller ID, checks the entered pair with one LWA refresh, and returns
the validated values for ELTA to seal. Refresh keeps the issuing pair and Seller ID
and replaces only the access and rotated refresh tokens. Only the secret and refresh
token are declared updatable; core owns the update.
B1 adds the CONSENT way beside it once the operator configures the client's public SP-API
app (below). It stays out of the source's connect until then, so an unconfigured deployment
offers the private app alone and the source remains available. The seller picks their Seller
Central store, signs in and approves the app; Amazon returns state,
selling_partner_id and spapi_oauth_code, which ELTA exchanges with the public app pair for a
grant sealing only refresh_token, access_token and selling_partner_id. A consent grant's
deadline counts Amazon's 365-day reauthorization rule from its latest successful consent, never
the private secret's 180 days. ELTA_LWA_TOKEN_URL optionally overrides the token endpoint for
Seller apps, private and public; Amazon Ads consent, token and API hosts follow the store's
sales region (NA/EU/FE).
Seller LWA invalid_client for the seller's own private app is AUTH_INVALID, naming the client
secret, so the seller can update a rotated secret; for our operator public app, and for Ads, the
same code stays REQUEST_REJECTED. invalid_grant requires reconnect. Permission hints translate
Keble's instructions into English and Chinese while keeping Amazon's role, permission, and menu
names in English inside both texts.
Operator setup for the public app
- In Seller Central > Apps and Services > Develop Apps, register the public SP-API app and
note its Application ID (
amzn1.sellerapps.app.…, for the consent URL) and its LWA client ID/secret (amzn1.application-oa2-client.…, for the code exchange and refresh). - Register the app's Log-in URI as the keble.ai page that forwards the signed-in seller to
Amazon's callback (
/stores/login) and its Redirect URI as/stores/callback. The log-in page acceptsamazon_callback_urionly over HTTPS from the saved chosen site's origin, and forwardsversionexactly as received. Both pages sendReferrer-Policy: no-referrer. - Write
ELTA_SELLER_PUBLIC_APP_APPLICATION_ID,ELTA_SELLER_PUBLIC_APP_CLIENT_IDandELTA_SELLER_PUBLIC_APP_CLIENT_SECRETonly in the environment whose/stores/loginLog-in URI is registered on the Amazon app (that environment is where Amazon returns the callback), then config-roll the three elta2 services there. Whether one Amazon app accepts more than one Log-in URI is unconfirmed; confirm it in Developer Central before activation. A keble-test check therefore needs either the app pointed at keble-test first or a second Draft app registered for it. While the app is a Draft leaveELTA_SELLER_PUBLIC_APP_DRAFT=true(which addsversion=betato the consent URL); set it tofalseafter Amazon publishes the app. CONSENT is hidden until all three values are set. - Amazon forces every LWA client secret to rotate about every 180 days. When the public pair
is rotated, write the new secret and
ELTA_SELLER_PUBLIC_APP_SECRET_ROTATED_AT(that real UTC instant, ISO 8601) in the scope that holds the pair (step 3's environment; a second keble-test Draft app has its own scope and its own rotation), then config-roll that environment's elta2 services. Readiness then reportsapp_renewalsforamazon.selleras that instant + 180 days; with no declared instant the configured pair still warns with a nullrenew_by. No instant is inferred from import history. An expired public secret is ours to rotate: its 403 isREQUEST_REJECTED(SUPPORT), never a customer reconnect.
Generated clients
src/elta_amz/_generated/ is moved verbatim from ELTA1
elta.backend/amazon/access/_generated/ with only import paths fixed
(amazon.access._generated -> elta_amz._generated, schemas ->
elta_amz._generated._schemas). The two hand-written base modules are
self-contained: the keble_helpers model config is inlined as a pydantic
ConfigDict, and ELTA1's raw-response persistence classes are dropped because
ELTA2 archives raw bytes and stores change-only facts. pyrightconfig.json
ignores the generated implementations (types are still resolved on demand), and
ruff excludes the directory.
ELTA1's amazon/access/generated/*.pyi overlay was not moved: 185 of its 200
stubs described a persistence/ wrapper layer that no longer exists, and the
remaining Any stubs would shadow the real generated models, whose types the
pyright ignore rule resolves on demand (verified: a bogus field is still
reported).
ELTA1's operation registry (amazon/access/common/catalog/_operation_registry.py,
10M) and API spec (amazon/access/_api_spec/, 32M) were left behind: no moved
generated module imports them; E1 decides whether a reader needs them.
Checks
uv sync
uv run pytest -q
npx --yes pyright .
uv run ruff check .
Metadata
Release files for elta-amz 0.22.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| elta_amz-0.22.0-py3-none-any.whl | Python 3 | none | any | Details for elta_amz-0.22.0-py3-none-any.whl |
Release files / elta_amz-0.22.0-py3-none-any.whl
| Download URL | elta_amz-0.22.0-py3-none-any.whl |
|---|---|
| Size | 1.6 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
63340906c7754082124e68c08f31fa9ad35c1d925fbef98e8606e78bbf29283d
|
|
BLAKE2b-256 checksum How to use checksums |
58c6d99e9113e465b157f32b4886bc264eb190d964cea5cc383d15feed00610d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for elta-amz 0.22.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.