{"x402Version":2,"service":"HALOWERK handelswerk","version":"1.0.0","network":"eip155:8453","network_name":"Base Mainnet","chain_id":8453,"recipient":"0x2880EdfFF13100677Bf97A3CBdF3Bc34771C4E5E","asset":{"symbol":"USDC","address":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","decimals":6},"facilitators":["CDP","https://facilitator.xpay.sh"],"payment_headers":{"primary":"PAYMENT-SIGNATURE","accepted":["PAYMENT-SIGNATURE","X-Payment","PAYMENT"],"challenge":["PAYMENT-REQUIRED"],"response":["PAYMENT-RESPONSE"]},"resources":[{"url":"https://handel.halowerk.com/v1/local-business","method":"POST","name":"local_business","description":"Searches OpenStreetMap through Overpass for businesses of a chosen trade within a radius of a coordinate, and returns each with its name, address, opening hours, phone, website, and the distance from your point, sorted nearest first. Around thirty trades are mapped to the OSM tags that actually hold them, because OSM is indexed by tags and not by free text — a plain word search finds almost nothing there. Coverage is what volunteers have mapped: dense in cities, thin in rural areas, and a business absent here may simply never have been entered, which is stated rather than presented as an empty market. Overpass rejects requests over quota with a normal-looking empty answer; that case is detected and reported as an upstream condition instead of being passed off as no results. Data is ODbL and attribution is required on any reuse.","summary":"Find businesses of a given trade around a coordinate, with address, opening hours, contact details and distance, sourced from OpenStreetMap.","inputSchema":{"type":"object","required":["latitude","longitude","trade"],"additionalProperties":false,"properties":{"latitude":{"type":"number","minimum":-90,"maximum":90,"description":"Centre latitude."},"longitude":{"type":"number","minimum":-180,"maximum":180,"description":"Centre longitude."},"trade":{"type":"string","enum":["bakery","butcher","supermarket","restaurant","cafe","bar","pharmacy","doctor","dentist","hotel","bank","atm","fuel","car_repair","hairdresser","hardware","electronics","clothes","bookshop","florist","optician","veterinary","school","kindergarten","post_office","laundry","bicycle","craft","office","any_shop"],"description":"Which trade to search for."},"radius_km":{"type":"number","minimum":0.1,"maximum":25,"default":2,"description":"Search radius in kilometres."},"limit":{"type":"integer","minimum":1,"maximum":100,"default":20,"description":"How many results."},"require_name":{"type":"boolean","default":true,"description":"Skip entries with no name — unnamed points are rarely useful."},"open_now_only":{"type":"boolean","default":false,"description":"Only entries that declare opening hours (the hours are returned, not evaluated)."}}},"mimeType":"application/json","accepts":[{"scheme":"exact","network":"eip155:8453","payTo":"0x2880EdfFF13100677Bf97A3CBdF3Bc34771C4E5E","price":{"amount":"5000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","extra":{"asset":"USDC","network_name":"Base Mainnet","name":"USD Coin","version":"2","assetTransferMethod":"eip3009","eip712Domain":{"name":"USD Coin","version":"2","chainId":8453,"verifyingContract":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"}}},"maxTimeoutSeconds":300}]},{"url":"https://handel.halowerk.com/v1/registry-snapshot","method":"POST","name":"registry_snapshot","description":"Looks up a legal entity in GLEIF, the worldwide Legal Entity Identifier register, by LEI or by name, and turns the raw record into an answer. GLEIF returns keys rather than statements: the legal form arrives as a code like 6QQB and the register as RA000304, so both are resolved against the GLEIF code lists into the legal form in its own language and the competent register with its website. registered_as carries the local file number, which is what actually lets a caller pull the national register entry. Two quality signals travel with every answer because they decide how much the record is worth. registration_status distinguishes an issued record from a lapsed one, where the annual confirmation was missed and the details may be stale. corroboration_level says whether the entry was checked against an official source or supplied by the company alone and never verified, which is the difference between a register extract and a self-declaration; an endpoint that hides this makes the two look identical. Relationships to the ultimate parent and to direct subsidiaries are included where GLEIF records them. Management and directors are not returned and cannot be: GLEIF records no corporate bodies, so the field stays null with the reason attached rather than being filled from elsewhere. Absence from GLEIF means the entity has no LEI, which is common for small companies and is not evidence that it does not exist.","summary":"Register status of a legal entity from the global LEI register: legal form and register spelled out rather than left as codes, official seat, the competent register with its local file number, renewal dates and how well the record is corroborated.","inputSchema":{"type":"object","additionalProperties":false,"properties":{"lei":{"type":"string","pattern":"^[A-Z0-9]{20}$","description":"Legal Entity Identifier, 20 characters. The precise route."},"name":{"type":"string","minLength":2,"maxLength":200,"description":"Legal name to search for, when the LEI is unknown."},"country":{"type":"string","pattern":"^[A-Za-z]{2}$","description":"ISO country code narrowing a name search, for example DE."},"include_relationships":{"type":"boolean","default":true,"description":"Also resolve ultimate parent and direct subsidiaries."}}},"mimeType":"application/json","accepts":[{"scheme":"exact","network":"eip155:8453","payTo":"0x2880EdfFF13100677Bf97A3CBdF3Bc34771C4E5E","price":{"amount":"5000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","extra":{"asset":"USDC","network_name":"Base Mainnet","name":"USD Coin","version":"2","assetTransferMethod":"eip3009","eip712Domain":{"name":"USD Coin","version":"2","chainId":8453,"verifyingContract":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"}}},"maxTimeoutSeconds":300}]},{"url":"https://handel.halowerk.com/v1/slotting-plan","method":"POST","name":"slotting_plan","description":"Takes a warehouse as a table and returns a placement. You supply the storage locations with their walking distance to the pick-and-drop point and, where they exist, their weight and volume limits; you supply the SKUs with pick frequency, weight and volume; and you may supply the joint-pick pairs. The endpoint classifies the SKUs into A, B and C by cumulative pick share, groups the SKUs that are picked together into affinity clusters so that they are slotted next to each other, and then assigns clusters to the shortest free locations in descending order of pick frequency, skipping any location whose weight or volume limit the SKU would break. The travel distance is arithmetic, not an estimate: pick frequency times slot distance, doubled when the picker returns, summed over all SKUs. Where every SKU carries a current_location_id the same sum is computed for the existing layout and reported as the saving, so the plan can be judged rather than believed. The assignment heuristic is fixed and every ordering is decided by the input alone, so the same request always yields the same plan; it is a good placement, not a proven optimum, because the full problem is a quadratic assignment problem. This endpoint does not know your aisles: the distance per location is what you pass in, it is never derived from a floor plan, and nothing is stored between calls.","summary":"Assign SKUs to storage locations from your own pick frequencies, weights and slot distances, and return the placement with the travel distance recomputed against your current layout.","inputSchema":{"type":"object","required":["skus","locations"],"additionalProperties":false,"properties":{"skus":{"type":"array","minItems":1,"maxItems":2000,"description":"The SKUs to place.","items":{"type":"object","required":["sku","picks_per_period"],"additionalProperties":false,"properties":{"sku":{"type":"string","minLength":1,"maxLength":64,"description":"Your SKU identifier. Must be unique within the request."},"picks_per_period":{"type":"number","minimum":0,"maximum":1000000,"description":"Number of picks in the period you are planning for. The period itself is yours; it only has to be the same for every SKU."},"weight_kg":{"type":"number","minimum":0,"maximum":100000,"description":"Weight of one storage unit in kilograms. Checked against max_weight_kg of the location."},"volume_l":{"type":"number","minimum":0,"maximum":100000,"description":"Volume of one storage unit in litres. Checked against max_volume_l of the location."},"current_location_id":{"type":"string","maxLength":64,"description":"Where the SKU sits today. Only used for the before-and-after comparison."}}}},"locations":{"type":"array","minItems":1,"maxItems":5000,"description":"The storage locations available for the plan.","items":{"type":"object","required":["location_id","travel_distance_m"],"additionalProperties":false,"properties":{"location_id":{"type":"string","minLength":1,"maxLength":64,"description":"Your location identifier. Must be unique within the request."},"travel_distance_m":{"type":"number","minimum":0,"maximum":100000,"description":"One-way walking distance in metres from the pick-and-drop point to this location."},"zone":{"type":"string","maxLength":64,"description":"Free-text zone label, passed through unchanged."},"max_weight_kg":{"type":"number","minimum":0,"maximum":100000,"description":"Weight limit of this location in kilograms. Omitted means no limit."},"max_volume_l":{"type":"number","minimum":0,"maximum":100000,"description":"Volume limit of this location in litres. Omitted means no limit."}}}},"affinities":{"type":"array","maxItems":5000,"description":"Pairs of SKUs that are picked together. Used to slot them near each other.","items":{"type":"object","required":["sku_a","sku_b","joint_picks_per_period"],"additionalProperties":false,"properties":{"sku_a":{"type":"string","minLength":1,"maxLength":64},"sku_b":{"type":"string","minLength":1,"maxLength":64},"joint_picks_per_period":{"type":"number","minimum":0,"maximum":1000000,"description":"How often the two are picked in the same order, in the same period as picks_per_period."}}}},"abc_share_pct":{"type":"array","minItems":2,"maxItems":2,"default":[80,95],"items":{"type":"number","minimum":0,"maximum":100},"description":"Cumulative pick share in percent that ends class A and class B. First value must be smaller than the second."},"return_trip":{"type":"boolean","default":true,"description":"Whether the picker walks back the same way. True doubles every distance."}}},"mimeType":"application/json","accepts":[{"scheme":"exact","network":"eip155:8453","payTo":"0x2880EdfFF13100677Bf97A3CBdF3Bc34771C4E5E","price":{"amount":"5000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","extra":{"asset":"USDC","network_name":"Base Mainnet","name":"USD Coin","version":"2","assetTransferMethod":"eip3009","eip712Domain":{"name":"USD Coin","version":"2","chainId":8453,"verifyingContract":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"}}},"maxTimeoutSeconds":300}]},{"url":"https://handel.halowerk.com/v1/container-load","method":"POST","name":"container_load","description":"Loads a package list into one loading space and returns the plan, not an estimate. The floor starts as one free surface; packages are sorted by footprint, then height, then weight, then identifier, and each one is placed on the lowest, then frontmost, then smallest free surface it fits on, turned by 90 degrees around the vertical axis where that makes it fit. Every placement splits the surface it used into two remainders and, where the package may be stacked on, opens a new free surface on top of it at its own height, so the floor is filled before anything is stacked and a stack is only ever built where the floor has run out. Packages are never tipped, so the stated height stays the height. Every placement comes back with its x, y and z coordinate in millimetres, its orientation, its stack level and the package it rests on, which makes the plan checkable rather than merely plausible. Three limits are enforced and every rejection names the limit it hit: loading stops before max_payload_kg is exceeded, no surface is opened on a package marked stackable false, and max_stack_load_kg is checked against the whole chain of packages underneath before a placement is made, so it constrains the plan rather than warning about it afterwards; the same check is run again over the finished plan and its result is reported. The result gives volume and floor-area utilization, payload utilization, the highest stack level, the centre of gravity in all three axes and, when two axle groups are given, the static payload share on each of them by the lever rule, flagged when it exceeds max_load_kg or when the centre of gravity falls outside the axle span. Every ordering is decided by the input, so the same request always returns the same plan; it is a good load, not a proven optimum, because three-dimensional packing is NP-hard, and a guillotine split cannot reuse an L-shaped remainder, which is stated in the response rather than hidden. This is not load securing: lashing forces, friction coefficients and VDI 2700 are out of scope, and so is any dynamic axle load.","summary":"Plan a container or trailer load from your own package list: placement coordinates per package, volume and payload utilization, stack load per supporting package, centre of gravity and the static two-axle load split.","inputSchema":{"type":"object","required":["container","items"],"additionalProperties":false,"properties":{"container":{"type":"object","required":["length_mm","width_mm","height_mm","max_payload_kg"],"additionalProperties":false,"description":"Inner loading space and payload of the container, trailer or swap body.","properties":{"length_mm":{"type":"number","minimum":1,"maximum":30000,"description":"Inner length in millimetres. The x axis, measured from the front wall."},"width_mm":{"type":"number","minimum":1,"maximum":5000,"description":"Inner width in millimetres. The y axis."},"height_mm":{"type":"number","minimum":1,"maximum":5000,"description":"Inner height in millimetres. The z axis."},"max_payload_kg":{"type":"number","minimum":0,"maximum":100000,"description":"Payload in kilograms. Loading stops before this is exceeded."}}},"items":{"type":"array","minItems":1,"maxItems":200,"description":"The packages to load. Each entry is one type with a quantity.","items":{"type":"object","required":["item_id","length_mm","width_mm","height_mm","weight_kg"],"additionalProperties":false,"properties":{"item_id":{"type":"string","minLength":1,"maxLength":64,"description":"Your identifier for this package type. Must be unique within the request."},"length_mm":{"type":"number","minimum":1,"maximum":30000,"description":"Length of one package in millimetres."},"width_mm":{"type":"number","minimum":1,"maximum":30000,"description":"Width of one package in millimetres."},"height_mm":{"type":"number","minimum":1,"maximum":30000,"description":"Height of one package in millimetres. Never used as a footprint side: packages are not tipped."},"weight_kg":{"type":"number","minimum":0,"maximum":100000,"description":"Weight of one package in kilograms."},"quantity":{"type":"integer","minimum":1,"maximum":1000,"default":1,"description":"How many packages of this type."},"stackable":{"type":"boolean","default":true,"description":"Whether anything may be placed on top of this package. False ends the stack above it."},"rotatable":{"type":"boolean","default":true,"description":"Whether the package may be turned by 90 degrees around the vertical axis. Never tipped."},"max_stack_load_kg":{"type":"number","minimum":0,"maximum":100000,"description":"How much weight one package can carry on top of it. Checked against the load actually resting on it."}}}},"axles":{"type":"array","minItems":2,"maxItems":2,"description":"Exactly two axle groups, for the static axle load. With more than two the load split is statically indeterminate and cannot be computed from geometry alone, so only two are accepted.","items":{"type":"object","required":["axle_id","position_mm"],"additionalProperties":false,"properties":{"axle_id":{"type":"string","minLength":1,"maxLength":32,"description":"Your label for this axle group, for example front or bogie."},"position_mm":{"type":"number","minimum":-30000,"maximum":60000,"description":"Position along the x axis in millimetres, measured from the front wall of the loading space. May be negative if the axle sits ahead of it."},"max_load_kg":{"type":"number","minimum":0,"maximum":100000,"description":"Permitted load on this axle group in kilograms, payload share only."}}}}}},"mimeType":"application/json","accepts":[{"scheme":"exact","network":"eip155:8453","payTo":"0x2880EdfFF13100677Bf97A3CBdF3Bc34771C4E5E","price":{"amount":"6000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","extra":{"asset":"USDC","network_name":"Base Mainnet","name":"USD Coin","version":"2","assetTransferMethod":"eip3009","eip712Domain":{"name":"USD Coin","version":"2","chainId":8453,"verifyingContract":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"}}},"maxTimeoutSeconds":300}]},{"url":"https://handel.halowerk.com/v1/invoice-extract","method":"POST","name":"invoice_extract","description":"Reads a hybrid invoice and returns it as data. Accepts a PDF with an embedded ZUGFeRD or Factur-X XML, or the EN 16931 XML on its own, in either syntax the standard allows: CII, which ZUGFeRD and Factur-X use, and UBL, which XRechnung and Peppol BIS use. Both are mapped onto one flat result, so a caller does not have to know which syntax arrived: invoice number, type code, issue, delivery and due date, currency, profile identifier, buyer reference and order reference, seller and buyer with name, VAT number, legal identifier and address country, the payment means with IBAN and BIC, every line with quantity and unit code, net unit price, line net amount and tax category and rate, the tax breakdown per rate with taxable basis and tax amount, and the document totals from line total through tax basis, tax total and grand total to prepaid and amount due. The stated totals are then recomputed from the extracted parts in whole cents and every deviation is reported with the stated figure, the computed figure and the difference, with a one cent per tax group treated as rounding rather than as an error by the issuer. The result can be posted straight to /v1/invoice-audit for the full recomputation. Extraction is deterministic and literal: nothing is inferred, no model is involved, no external source is called, and a field that is not in the document comes back as null and is named in unavailable_fields. Scanned invoices are explicitly out of scope. A PDF that carries no embedded EN 16931 XML is rejected with a machine-readable reason and is never guessed at with text recognition, because a guessed invoice that is posted is a wrong booking that nobody notices in time.","summary":"Pull the EN 16931 structure out of a ZUGFeRD or Factur-X PDF or an XRechnung: header, parties, lines, tax breakdown, totals and payment terms, with the stated totals recomputed.","inputSchema":{"type":"object","required":["document_base64"],"additionalProperties":false,"properties":{"document_base64":{"type":"string","minLength":16,"maxLength":250000,"description":"The document as base64. Either a PDF with an embedded ZUGFeRD or Factur-X XML, or the EN 16931 XML itself (CII or UBL). The JSON body of this hub is capped at 256 kB, so the base64 text must stay below 250000 characters, which is roughly 187 kB of file."},"include_lines":{"type":"boolean","default":true,"description":"Whether to return the individual invoice lines. False returns only header, tax breakdown and totals."},"verify_totals":{"type":"boolean","default":true,"description":"Whether to recompute the stated totals from the lines and the tax breakdown and report every deviation."}}},"mimeType":"application/json","accepts":[{"scheme":"exact","network":"eip155:8453","payTo":"0x2880EdfFF13100677Bf97A3CBdF3Bc34771C4E5E","price":{"amount":"4000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","extra":{"asset":"USDC","network_name":"Base Mainnet","name":"USD Coin","version":"2","assetTransferMethod":"eip3009","eip712Domain":{"name":"USD Coin","version":"2","chainId":8453,"verifyingContract":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"}}},"maxTimeoutSeconds":300}]},{"url":"https://handel.halowerk.com/v1/demand-forecast","method":"POST","name":"demand_forecast","description":"Forecasts one SKU from a history you supply. The pipeline is fixed and fully disclosed in the response rather than hidden behind a score. The series is decomposed multiplicatively while every observation is positive and additively as soon as a zero or a negative appears, because a ratio is not defined there; the seasonal index is the median ratio per phase against a centred moving average, estimated only on periods that carry no promotion and no holiday so that a campaign in week twelve does not become the season of week twelve; the promotion and holiday factors are then estimated on the deseasonalised series against the quiet periods; the remainder is fitted with a Holt linear trend at fixed smoothing constants, deliberately fixed because tuning them per call would make the answer depend on a search that cannot be reproduced. The forecast recombines trend, season and the events you flag for the future periods, and the prediction interval comes from the standard deviation of the in-sample one-step errors widened by the square root of the horizon. Two baselines are always computed and reported even when they beat the method: the naive last value and the seasonal naive value one season back. A backtest holds back the tail of the history, refits the identical pipeline on the remainder and reports MAE, RMSE and MAPE for all three, so the forecast can be judged rather than believed. Everything is arithmetic on the data you send: no weather, no external source, no stored state, and the same request always returns the same numbers. It forecasts one series per call, it does not do cannibalisation between SKUs, and a season it cannot estimate is reported as not applied rather than assumed.","summary":"Forecast demand for one SKU from your own history, promotion calendar and holidays, with a prediction interval, the fitted seasonal and event factors, and a backtest against two baselines.","inputSchema":{"type":"object","required":["history","frequency"],"additionalProperties":false,"properties":{"history":{"type":"array","minItems":4,"maxItems":520,"description":"The demand history, one entry per period, oldest first. Periods must be consecutive and each period_start must be unique and ascending.","items":{"type":"object","required":["period_start","quantity"],"additionalProperties":false,"properties":{"period_start":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"First day of the period as YYYY-MM-DD."},"quantity":{"type":"number","minimum":-1000000000,"maximum":1000000000,"description":"Units sold in that period. Zero is allowed and switches the decomposition to additive."},"promotion":{"type":"boolean","default":false,"description":"Whether the SKU was on promotion in that period."},"holiday":{"type":"boolean","default":false,"description":"Whether that period contained a holiday you consider relevant. The calendar is yours; no holiday list is looked up."}}}},"frequency":{"type":"string","enum":["daily","weekly","monthly"],"description":"Length of one period. Sets the default season length: 7 for daily, 52 for weekly, 12 for monthly."},"horizon_periods":{"type":"integer","minimum":1,"maximum":104,"default":8,"description":"How many periods to forecast."},"season_length_periods":{"type":"integer","minimum":0,"maximum":53,"description":"Override the season length in periods. Zero switches seasonality off. Omitted uses the default for the frequency."},"future_events":{"type":"array","maxItems":104,"description":"Promotions and holidays you already know about for the forecast periods. Matched on period_start against the generated periods; an entry that matches no period is reported back as unmatched.","items":{"type":"object","required":["period_start"],"additionalProperties":false,"properties":{"period_start":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"First day of the forecast period this applies to."},"promotion":{"type":"boolean","default":false},"holiday":{"type":"boolean","default":false}}}},"confidence_level":{"type":"number","enum":[0.8,0.9,0.95],"default":0.9,"description":"Confidence level of the prediction interval."},"backtest_periods":{"type":"integer","minimum":0,"maximum":52,"default":0,"description":"How many of the last periods to hold back for the comparison against the baselines. Zero picks a quarter of the history, capped at the horizon."}}},"mimeType":"application/json","accepts":[{"scheme":"exact","network":"eip155:8453","payTo":"0x2880EdfFF13100677Bf97A3CBdF3Bc34771C4E5E","price":{"amount":"6000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","extra":{"asset":"USDC","network_name":"Base Mainnet","name":"USD Coin","version":"2","assetTransferMethod":"eip3009","eip712Domain":{"name":"USD Coin","version":"2","chainId":8453,"verifyingContract":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"}}},"maxTimeoutSeconds":300}]},{"url":"https://handel.halowerk.com/v1/return-disposition","method":"POST","name":"return_disposition","description":"Takes a list of returns with the figures your own systems already hold and returns one decision per return, with the arithmetic that produced it. Four routes are valued: reselling as is, at the resale value weighted by the probability that it actually sells and less the restocking cost; repairing and reselling, at the refurbished value weighted by the repair success probability plus the salvage value on the failure branch, less the repair cost, which is incurred either way; recovering value through parts or material; and scrapping, which is a cost and never proceeds. Inspection and inbound freight are charged to every route because they are incurred whatever you decide, so they change the level but never the ranking, and both figures are reported separately for exactly that reason. A route whose inputs are missing is reported as not evaluable together with the field names it needs, never quietly valued at zero, and an omitted cost that is treated as zero is listed per item so no decision rests on a silent assumption. Where the best route is ahead of the runner-up by less than decision_margin_pct the result is marked ambiguous and no winner is asserted, because a decision inside the noise of your own cost estimates is not a decision. For the repair route the break-even repair cost is reported: the amount at which repairing stops being the better choice. Amounts are in the currency you name and are never converted. This is arithmetic on your figures, not a valuation service: it does not know what the item is worth, it does not look up market prices, it stores nothing, and it does not run your returns process.","summary":"Decide per return whether to resell, repair and resell, recover value or scrap, computed from your own resale, repair, inspection and freight figures, with the full arithmetic and the break-even repair cost.","inputSchema":{"type":"object","required":["items"],"additionalProperties":false,"properties":{"items":{"type":"array","minItems":1,"maxItems":500,"description":"The returns to decide on. Every amount is in the currency named at document level.","items":{"type":"object","required":["return_id"],"additionalProperties":false,"properties":{"return_id":{"type":"string","minLength":1,"maxLength":64,"description":"Your identifier for this return. Must be unique within the request."},"condition":{"type":"string","enum":["new","like_new","used","damaged","defective","unknown"],"description":"Condition as your inspection recorded it. Passed through unchanged; it does not change the arithmetic."},"resale_value":{"type":"number","minimum":0,"maximum":100000000,"description":"Expected proceeds from selling the item as it is."},"resale_probability":{"type":"number","minimum":0,"maximum":1,"default":1,"description":"Probability that the as-is resale actually happens within your planning window."},"refurb_resale_value":{"type":"number","minimum":0,"maximum":100000000,"description":"Expected proceeds after a successful repair."},"repair_cost":{"type":"number","minimum":0,"maximum":100000000,"description":"Cost of the repair attempt. Incurred whether or not the repair succeeds."},"repair_success_probability":{"type":"number","minimum":0,"maximum":1,"description":"Probability that the repair succeeds. A failed repair falls back to salvage_value."},"salvage_value":{"type":"number","minimum":0,"maximum":100000000,"description":"Proceeds from parts recovery or material recycling."},"disposal_cost":{"type":"number","minimum":0,"maximum":100000000,"description":"Cost of disposing of the item. Scrapping is a cost, not proceeds."},"inspection_cost":{"type":"number","minimum":0,"maximum":100000000,"description":"Cost of inspecting this return. Incurred on every route and therefore does not change the ranking, only the level."},"inbound_freight_cost":{"type":"number","minimum":0,"maximum":100000000,"description":"Freight already spent getting the item back. Incurred on every route."},"restocking_cost":{"type":"number","minimum":0,"maximum":100000000,"description":"Cost of putting the item back into stock. Only charged to the as-is resale route."}}}},"defaults":{"type":"object","additionalProperties":false,"description":"Values that apply to every item that does not carry its own. An item value always wins.","properties":{"resale_probability":{"type":"number","minimum":0,"maximum":1},"repair_cost":{"type":"number","minimum":0,"maximum":100000000},"repair_success_probability":{"type":"number","minimum":0,"maximum":1},"disposal_cost":{"type":"number","minimum":0,"maximum":100000000},"inspection_cost":{"type":"number","minimum":0,"maximum":100000000},"inbound_freight_cost":{"type":"number","minimum":0,"maximum":100000000},"restocking_cost":{"type":"number","minimum":0,"maximum":100000000}}},"currency":{"type":"string","minLength":3,"maxLength":3,"default":"EUR","description":"ISO 4217 code for every amount in this request. Not converted, only carried through."},"decision_margin_pct":{"type":"number","minimum":0,"maximum":100,"default":5,"description":"How far ahead the best route must be before it counts as a decision. Inside this margin the result is reported as ambiguous instead of asserting a winner."}}},"mimeType":"application/json","accepts":[{"scheme":"exact","network":"eip155:8453","payTo":"0x2880EdfFF13100677Bf97A3CBdF3Bc34771C4E5E","price":{"amount":"4000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","extra":{"asset":"USDC","network_name":"Base Mainnet","name":"USD Coin","version":"2","assetTransferMethod":"eip3009","eip712Domain":{"name":"USD Coin","version":"2","chainId":8453,"verifyingContract":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"}}},"maxTimeoutSeconds":300}]},{"url":"https://handel.halowerk.com/v1/landed-cost","method":"POST","name":"landed_cost","description":"Computes what an import actually costs at the destination. The customs value is assembled from goods, freight and insurance on the chosen basis (CIF or FOB), duty is applied to it, and import VAT is applied to the duty-inclusive value, which is the ordering most calculations get wrong. Duty rates come from the live tariff: the UK Trade Tariff for GB and the USITC HTS for the US, with the commodity description returned so a wrong classification is visible. For EU destinations only import VAT is computed — TARIC publishes no usable API, and rather than invent a duty rate the duty component is returned as null and flagged as outstanding, which is the honest state of the data. Reduced VAT rates, preferential origin, anti-dumping measures and quotas are not applied; a customs broker is not replaced.","summary":"Work out the full landed cost of an import — goods, freight, insurance, duty and import VAT — with the duty rate looked up in the official UK or US tariff.","inputSchema":{"type":"object","required":["hs_code","destination_country","goods_value"],"additionalProperties":false,"properties":{"hs_code":{"type":"string","minLength":4,"maxLength":14,"description":"Commodity code. UK wants 10 digits, US 8 to 10."},"destination_country":{"type":"string","minLength":2,"maxLength":2,"description":"ISO country code of the destination."},"origin_country":{"type":"string","minLength":2,"maxLength":2,"description":"ISO country code of origin, for context."},"goods_value":{"type":"number","minimum":0,"description":"Goods value in the given currency."},"freight_cost":{"type":"number","minimum":0,"default":0,"description":"Freight to the border."},"insurance_cost":{"type":"number","minimum":0,"default":0,"description":"Insurance."},"currency":{"type":"string","minLength":3,"maxLength":3,"default":"EUR","description":"Currency of all amounts. No conversion is done."},"valuation_basis":{"type":"string","enum":["CIF","FOB"],"default":"CIF","description":"CIF includes freight and insurance in the customs value, FOB does not."}}},"mimeType":"application/json","accepts":[{"scheme":"exact","network":"eip155:8453","payTo":"0x2880EdfFF13100677Bf97A3CBdF3Bc34771C4E5E","price":{"amount":"2000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","extra":{"asset":"USDC","network_name":"Base Mainnet","name":"USD Coin","version":"2","assetTransferMethod":"eip3009","eip712Domain":{"name":"USD Coin","version":"2","chainId":8453,"verifyingContract":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"}}},"maxTimeoutSeconds":300}]},{"url":"https://handel.halowerk.com/v1/vat-resolve","method":"POST","name":"vat_resolve","description":"Two answers in one call. Validation: the number is checked against the VIES service of the member state that issued it, with the consultation date returned. Treatment: given the supplier country, the customer country and whether the customer is a business, it states whether the supply is domestic with the local rate, an intra-community B2B supply where the reverse charge shifts the liability to the customer, a B2C supply taxed where the customer sits, or an export outside the EU. VIES returns the trader name and address masked as three dashes unless a requester VAT number is supplied; that placeholder is never passed through — the fields come back as null with the reason stated, because a dash string in a name field silently poisons whatever consumes it. Standard rates only, with their effective date: reduced rates depend on the goods and would be guesswork without a tariff code. Not tax advice.","summary":"Validate an EU VAT number against VIES and determine the applicable rate or reverse-charge treatment for a supply between two countries.","inputSchema":{"type":"object","required":["vat_number"],"additionalProperties":false,"properties":{"vat_number":{"type":"string","minLength":4,"maxLength":20,"description":"VAT number with country prefix, e.g. DE811907980."},"supplier_country":{"type":"string","minLength":2,"maxLength":2,"description":"ISO country code of the supplier, for the treatment question."},"customer_is_business":{"type":"boolean","default":true,"description":"Whether the customer is a business (B2B) or a consumer (B2C)."},"supply_type":{"type":"string","enum":["goods","services","digital_services"],"default":"goods","description":"What is being supplied."}}},"mimeType":"application/json","accepts":[{"scheme":"exact","network":"eip155:8453","payTo":"0x2880EdfFF13100677Bf97A3CBdF3Bc34771C4E5E","price":{"amount":"2000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","extra":{"asset":"USDC","network_name":"Base Mainnet","name":"USD Coin","version":"2","assetTransferMethod":"eip3009","eip712Domain":{"name":"USD Coin","version":"2","chainId":8453,"verifyingContract":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"}}},"maxTimeoutSeconds":300}]},{"url":"https://handel.halowerk.com/v1/invoice-audit","method":"POST","name":"invoice_audit","description":"Rebuilds an invoice from its lines and compares the result with the stated totals. Line by line it checks quantity times unit price against the line total, applies line and document discounts in the right order, groups the net amounts by tax rate and computes the tax per group, then compares net, tax and gross with what the document claims. All arithmetic runs in whole cents, because adding decimal amounts as floating point produces cent-level noise that reads like an error by the issuer when it is an error by the checker. Rounding differences up to one cent per tax group are reported separately from real discrepancies. It also checks the formal side: a due date before the invoice date, a tax rate that is not one of the country standard rates, a negative line without a credit-note marker, and a missing VAT number where the reverse charge is claimed.","summary":"Recompute an invoice from its line items: totals, tax per rate, discounts and rounding, and report every deviation with the exact amount.","inputSchema":{"type":"object","required":["lines"],"additionalProperties":false,"properties":{"lines":{"type":"array","minItems":1,"maxItems":500,"description":"The invoice lines.","items":{"type":"object","required":["quantity","unit_price"],"additionalProperties":false,"properties":{"description":{"type":"string","maxLength":300},"quantity":{"type":"number"},"unit_price":{"type":"number"},"line_total":{"type":"number","description":"The stated line total. Recomputed if absent."},"tax_rate":{"type":"number","minimum":0,"maximum":100,"description":"Tax rate in percent for this line."},"discount_pct":{"type":"number","minimum":0,"maximum":100,"description":"Discount on this line in percent."}}}},"stated_net":{"type":"number","description":"Net total as stated on the invoice."},"stated_tax":{"type":"number","description":"Tax total as stated."},"stated_gross":{"type":"number","description":"Gross total as stated."},"document_discount_pct":{"type":"number","minimum":0,"maximum":100,"description":"Discount on the whole document, applied after line discounts."},"default_tax_rate":{"type":"number","minimum":0,"maximum":100,"description":"Tax rate for lines that do not carry one."},"currency":{"type":"string","minLength":3,"maxLength":3,"default":"EUR"},"invoice_date":{"type":"string","maxLength":10,"description":"Invoice date as YYYY-MM-DD."},"due_date":{"type":"string","maxLength":10,"description":"Due date as YYYY-MM-DD."},"reverse_charge":{"type":"boolean","default":false,"description":"Whether the invoice claims the reverse charge."},"customer_vat_number":{"type":"string","maxLength":20,"description":"Customer VAT number, required for the reverse charge."},"country":{"type":"string","minLength":2,"maxLength":2,"description":"Country whose standard rates the tax rates are checked against."}}},"mimeType":"application/json","accepts":[{"scheme":"exact","network":"eip155:8453","payTo":"0x2880EdfFF13100677Bf97A3CBdF3Bc34771C4E5E","price":{"amount":"2000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","extra":{"asset":"USDC","network_name":"Base Mainnet","name":"USD Coin","version":"2","assetTransferMethod":"eip3009","eip712Domain":{"name":"USD Coin","version":"2","chainId":8453,"verifyingContract":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"}}},"maxTimeoutSeconds":300}]},{"url":"https://handel.halowerk.com/v1/po-invoice-match","method":"POST","name":"po_invoice_match","description":"Compares a purchase order against a delivery note and an invoice, line by line. Lines are paired by article number where both sides carry one, and otherwise by text similarity — a text pairing is marked as such with its similarity score, because quietly matching on similar wording is exactly how a wrong invoice gets approved. Per pair it reports the ordered, delivered and invoiced quantity, the agreed and invoiced unit price, and flags the four cases that matter: invoiced more than delivered, delivered more than ordered, a unit price above the order beyond your tolerance, and a line on the invoice with no counterpart at all. Tolerances for quantity and price are yours to set. All arithmetic runs in whole cents. It compares the documents you supply and knows nothing about what was actually agreed or received.","summary":"Three-way match of purchase order, delivery note and invoice: quantities, prices and totals per line, with over-delivery, over-billing and unmatched lines named.","inputSchema":{"type":"object","required":["purchase_order","invoice"],"additionalProperties":false,"properties":{"purchase_order":{"type":"array","minItems":1,"maxItems":300,"description":"Ordered lines.","items":{"type":"object","required":["quantity"],"additionalProperties":false,"properties":{"sku":{"type":"string","maxLength":100},"description":{"type":"string","maxLength":300},"quantity":{"type":"number"},"unit_price":{"type":"number"}}}},"delivery_note":{"type":"array","maxItems":300,"description":"Delivered lines. Optional — without it only a two-way match runs.","items":{"type":"object","required":["quantity"],"additionalProperties":false,"properties":{"sku":{"type":"string","maxLength":100},"description":{"type":"string","maxLength":300},"quantity":{"type":"number"}}}},"invoice":{"type":"array","minItems":1,"maxItems":300,"description":"Invoiced lines.","items":{"type":"object","required":["quantity"],"additionalProperties":false,"properties":{"sku":{"type":"string","maxLength":100},"description":{"type":"string","maxLength":300},"quantity":{"type":"number"},"unit_price":{"type":"number"}}}},"quantity_tolerance_pct":{"type":"number","minimum":0,"maximum":50,"default":0,"description":"Allowed quantity deviation in percent."},"price_tolerance_pct":{"type":"number","minimum":0,"maximum":50,"default":0,"description":"Allowed unit-price deviation in percent."},"text_match_threshold":{"type":"number","minimum":0.1,"maximum":1,"default":0.5,"description":"Minimum text similarity to pair lines without an article number."},"currency":{"type":"string","minLength":3,"maxLength":3,"default":"EUR"}}},"mimeType":"application/json","accepts":[{"scheme":"exact","network":"eip155:8453","payTo":"0x2880EdfFF13100677Bf97A3CBdF3Bc34771C4E5E","price":{"amount":"2000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","extra":{"asset":"USDC","network_name":"Base Mainnet","name":"USD Coin","version":"2","assetTransferMethod":"eip3009","eip712Domain":{"name":"USD Coin","version":"2","chainId":8453,"verifyingContract":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"}}},"maxTimeoutSeconds":300}]},{"url":"https://handel.halowerk.com/v1/gtin-resolve","method":"POST","name":"gtin_resolve","description":"Looks up a barcode number across Open Food Facts and a general product database, returning product name, brand, category, packaging, quantity and images where present. The check digit is computed locally before anything is queried: an invalid number is a typo, and reporting it as not found would send the caller looking in the wrong place. The GS1 country prefix is decoded and labelled for what it is — where the number was issued, not where the product was made, a distinction that is routinely confused. A prefix in the 2 range is flagged as an in-store number that exists only at the retailer who assigned it and is registered nowhere. Sources are named per field so a food entry from the open database is distinguishable from a general catalogue entry. Coverage is uneven: food is well covered, general goods much less, and absence is not evidence the product does not exist.","summary":"Resolve an EAN, UPC or GTIN to product, brand and packaging, with the check digit verified first and the issuing country prefix decoded.","inputSchema":{"type":"object","required":["gtin"],"additionalProperties":false,"properties":{"gtin":{"type":"string","minLength":8,"maxLength":14,"description":"EAN-8, EAN-13, UPC-A or GTIN-14."},"sources":{"type":"array","items":{"type":"string","enum":["openfoodfacts","upcitemdb"]},"description":"Which sources to query. Both if omitted."},"skip_checksum":{"type":"boolean","default":false,"description":"Query even when the check digit is wrong."}}},"mimeType":"application/json","accepts":[{"scheme":"exact","network":"eip155:8453","payTo":"0x2880EdfFF13100677Bf97A3CBdF3Bc34771C4E5E","price":{"amount":"5000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","extra":{"asset":"USDC","network_name":"Base Mainnet","name":"USD Coin","version":"2","assetTransferMethod":"eip3009","eip712Domain":{"name":"USD Coin","version":"2","chainId":8453,"verifyingContract":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"}}},"maxTimeoutSeconds":300}]},{"url":"https://handel.halowerk.com/v1/return-policy","method":"POST","name":"return_policy","description":"Fetches one public policy page in a real browser and turns it into a fixed schema: return window in days and what it counts from, who pays the return shipping, how the refund is issued and within how many days, any restocking fee, the required condition of the goods, the excluded product categories, the steps of the procedure, whether an RMA is needed, the contact route and whether a statutory right of withdrawal is mentioned. Every populated field carries a verbatim quote of at most 200 characters from the page, and anything the page does not say stays null and is listed in unavailable_fields — a guessed deadline is worse than none. The structuring runs through a language model at Groq in the United States, which is disclosed in full in every response including what leaves the machine and what the provider agreement says about training and retention; nothing is cached or stored. The response carries structured facts and short quotes as evidence, not a copy of the merchant text. robots.txt is honoured and a disallowed page is refused rather than fetched, login walls, captchas and paywalls end the call, and none of those refusals is charged. This is an extraction of what a page says, not legal advice and not a check of whether the terms are lawful.","summary":"Read a merchant return or refund policy page and get the terms as structured fields — window, who pays return shipping, refund method, restocking fee, exclusions and procedure — each backed by a verbatim quote from that page.","inputSchema":{"type":"object","required":["url"],"additionalProperties":false,"properties":{"url":{"type":"string","format":"uri","description":"The https address of the return, refund or withdrawal policy page. Give the policy page itself, not the shop home page."},"language":{"type":"string","enum":["de","en","auto"],"default":"auto","description":"Language of the quotes to expect. Only affects the reading, never the wording of the quotes themselves."}}},"mimeType":"application/json","accepts":[{"scheme":"exact","network":"eip155:8453","payTo":"0x2880EdfFF13100677Bf97A3CBdF3Bc34771C4E5E","price":{"amount":"10000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","extra":{"asset":"USDC","network_name":"Base Mainnet","name":"USD Coin","version":"2","assetTransferMethod":"eip3009","eip712Domain":{"name":"USD Coin","version":"2","chainId":8453,"verifyingContract":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"}}},"maxTimeoutSeconds":300}]},{"url":"https://handel.halowerk.com/v1/parcel-normalize","method":"POST","name":"parcel_normalize","description":"Does two things that every shipping integration rebuilds and every one of them differently. First, carrier detection: the number is matched against the known formats and, where the format carries one, the check digit is actually computed — the UPS 1Z digit, the Universal Postal Union S10 digit and the GS1 mod-10 digit. This matters because pattern alone does not separate the formats: twelve digits can be DHL Paket or FedEx, fourteen can be GLS, DPD or Hermes. A passing check digit raises confidence sharply, a failing one rules that carrier out rather than merely lowering it, and everything that stays ambiguous comes back as a ranked candidate list with the matched rule and a reason, never as a single asserted carrier. For S10 numbers the country code identifies the postal operator that accepted the item. Second, status normalization: free-text event descriptions are mapped onto ten canonical states, each carrying its phase, whether it ends the journey and whether it is a disruption, plus the exact phrase that triggered the match so a caller can check and override the mapping. Rules are ordered from specific to general so that a failed delivery attempt is not swallowed by the word delivered. Unrecognised text becomes unknown with confidence zero and is never guessed into in_transit, because a wrongly assumed state triggers a wrong decision. There is no network access: this endpoint validates and normalizes what it is given and cannot confirm that a parcel exists or fetch its live status.","summary":"Identify the carrier from a tracking number using real check-digit arithmetic, and map free-text carrier status messages in German or English onto one common vocabulary with a phase, a terminal flag and an exception flag per event.","inputSchema":{"type":"object","additionalProperties":false,"properties":{"tracking_number":{"type":"string","minLength":4,"maxLength":40,"description":"Tracking number to identify. Spaces and hyphens are ignored."},"events":{"type":"array","maxItems":200,"description":"Carrier status messages to normalize onto the common vocabulary.","items":{"type":"object","additionalProperties":false,"properties":{"status":{"type":"string","maxLength":500,"description":"Raw status text from the carrier, German or English."},"timestamp":{"type":"string","maxLength":40,"description":"Optional time of the event, passed through unchanged."},"location":{"type":"string","maxLength":200,"description":"Optional location, passed through unchanged."}}}}}},"mimeType":"application/json","accepts":[{"scheme":"exact","network":"eip155:8453","payTo":"0x2880EdfFF13100677Bf97A3CBdF3Bc34771C4E5E","price":{"amount":"2000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","extra":{"asset":"USDC","network_name":"Base Mainnet","name":"USD Coin","version":"2","assetTransferMethod":"eip3009","eip712Domain":{"name":"USD Coin","version":"2","chainId":8453,"verifyingContract":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"}}},"maxTimeoutSeconds":300}]},{"url":"https://handel.halowerk.com/v1/price-elasticity","method":"POST","name":"price_elasticity","description":"Fits a constant-elasticity demand curve to the price and sales series you supply and returns the elasticity with its standard error, t statistic, two-sided p value and a Student t confidence interval, not a normal one, because at eight observations the difference in interval width is double-digit percent and a too narrow interval is exactly the kind of number a machine reuses unchecked. The competitor price can be added as a second regressor, giving the cross-price elasticity, and a promotion indicator can be added so that a campaign is not attributed to the price; in both cases you bring the figures and nothing is looked up. From the fitted elasticity the contribution-optimal price follows in closed form as unit cost times b over one plus b, and it is also evaluated at both ends of the confidence interval so the answer comes as a range rather than a false decimal. Where the elasticity is greater than minus one there is no interior optimum, and where it comes out positive the model says demand rises with price; in both cases the optimal price is returned as null with the reason stated instead of a number. An observation with zero units cannot enter a log fit; it is excluded, counted and named. If your price barely moved across the series the estimate rests on noise, and the price variation is measured and flagged rather than left for the caller to notice. A price grid you supply is evaluated at the fitted model with predicted units and contribution per candidate. This measures a relationship in observational data and never asserts a cause: it does not know your competitors, it does not look up market prices, it does not model stock-outs, cannibalisation or reference-price effects, and it stores nothing between calls.","summary":"Estimate own-price elasticity from your own price and sales series by log-log regression with standard error and confidence interval, and return the contribution-optimal price with the predicted units and contribution.","inputSchema":{"type":"object","required":["observations"],"additionalProperties":false,"properties":{"observations":{"type":"array","minItems":4,"maxItems":2000,"description":"Your own price and sales history for one SKU. Every amount is in the currency named at document level.","items":{"type":"object","required":["price","units_sold"],"additionalProperties":false,"properties":{"price":{"type":"number","exclusiveMinimum":0,"maximum":100000000,"description":"Selling price in that period. Must be positive: the estimation is on logarithms."},"units_sold":{"type":"number","minimum":0,"maximum":1000000000,"description":"Units sold at that price. A zero cannot enter a log-log fit and is excluded, reported and never silently dropped."},"period_start":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional period label as YYYY-MM-DD, passed through unchanged."},"promotion":{"type":"boolean","default":false,"description":"Whether the period was a promotion. Enters the fit as a separate indicator when include_promotion is true, so that a campaign is not attributed to the price."},"competitor_price":{"type":"number","exclusiveMinimum":0,"maximum":100000000,"description":"Competitor price in that period. Only used when include_competitor_price is true; you bring the figure, nothing is looked up."}}}},"unit_cost":{"type":"number","minimum":0,"maximum":100000000,"description":"Variable cost per unit. Required for the contribution-optimal price; without it only the elasticity is returned."},"include_competitor_price":{"type":"boolean","default":false,"description":"Whether to add the log competitor price as a second regressor and report the cross-price elasticity. Every observation must then carry competitor_price."},"include_promotion":{"type":"boolean","default":false,"description":"Whether to add the promotion indicator as a regressor."},"price_grid":{"type":"array","maxItems":200,"items":{"type":"number","exclusiveMinimum":0,"maximum":100000000},"description":"Candidate prices to evaluate with predicted units and contribution. Evaluated at the fitted model, in the order you give them."},"confidence_level":{"type":"number","enum":[0.8,0.9,0.95],"default":0.95,"description":"Confidence level for the elasticity interval. Student t, not normal."},"currency":{"type":"string","minLength":3,"maxLength":3,"default":"EUR","description":"ISO 4217 code for every amount in this request. Not converted, only carried through."}}},"mimeType":"application/json","accepts":[{"scheme":"exact","network":"eip155:8453","payTo":"0x2880EdfFF13100677Bf97A3CBdF3Bc34771C4E5E","price":{"amount":"5000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","extra":{"asset":"USDC","network_name":"Base Mainnet","name":"USD Coin","version":"2","assetTransferMethod":"eip3009","eip712Domain":{"name":"USD Coin","version":"2","chainId":8453,"verifyingContract":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"}}},"maxTimeoutSeconds":300}]},{"url":"https://handel.halowerk.com/v1/allergen-check","method":"POST","name":"allergen_check","description":"Returns what a product declares about allergens: the allergen tags, the trace warnings, the ingredients text in its original language, and the completeness of the record. The distinction it holds to throughout is between not declared and not present. The data come from volunteers and manufacturer submissions, so an empty allergen field means nobody entered one, and for somebody with an allergy that difference is the difference that matters — every absent allergen is therefore reported as not declared, never as absent. The fourteen allergens requiring declaration in the EU are each given a status of declared, trace or not declared so the gap is explicit rather than inferred from a short list. Completeness of the record, when it was last edited and by how many contributors are returned as the honest measure of how much weight the entry can carry. For an actual allergy the packaging governs, and the response says so.","summary":"Report the declared allergens and trace warnings of a food product with the original fields and data completeness — stating not declared rather than not present for anything absent.","inputSchema":{"type":"object","required":["barcode"],"additionalProperties":false,"properties":{"barcode":{"type":"string","minLength":8,"maxLength":20}}},"mimeType":"application/json","accepts":[{"scheme":"exact","network":"eip155:8453","payTo":"0x2880EdfFF13100677Bf97A3CBdF3Bc34771C4E5E","price":{"amount":"5000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","extra":{"asset":"USDC","network_name":"Base Mainnet","name":"USD Coin","version":"2","assetTransferMethod":"eip3009","eip712Domain":{"name":"USD Coin","version":"2","chainId":8453,"verifyingContract":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"}}},"maxTimeoutSeconds":300}]},{"url":"https://handel.halowerk.com/v1/ingredient-decoder","method":"POST","name":"ingredient_decoder","description":"Returns the ingredient list of a product as a structured hierarchy including sub-ingredients, with each additive resolved to its E number and name, the percentage where declared, and the origin markers such as palm oil or vegan and vegetarian status as the record carries them. What separates this from the usual ingredient parse is that unresolved components are a first-class result rather than dropped: an analysis that silently omits what it could not identify makes a list with five recognised ingredients out of twenty look complete, and the unresolved ones are precisely where an automated reading stops and a human has to look. The count and the names of unknown components are therefore returned, along with the share of the list that was resolved. Additive numbers are given as the record states them without a safety assessment attached, since permissibility and limits depend on the jurisdiction and the food category and vary between both.","summary":"Normalise the ingredients of a product into a hierarchy with additives resolved to their E numbers — and the unresolved components reported as a result in their own right.","inputSchema":{"type":"object","required":["barcode"],"additionalProperties":false,"properties":{"barcode":{"type":"string","minLength":8,"maxLength":20}}},"mimeType":"application/json","accepts":[{"scheme":"exact","network":"eip155:8453","payTo":"0x2880EdfFF13100677Bf97A3CBdF3Bc34771C4E5E","price":{"amount":"5000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","extra":{"asset":"USDC","network_name":"Base Mainnet","name":"USD Coin","version":"2","assetTransferMethod":"eip3009","eip712Domain":{"name":"USD Coin","version":"2","chainId":8453,"verifyingContract":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"}}},"maxTimeoutSeconds":300}]},{"url":"https://handel.halowerk.com/v1/nutrition-eco","method":"POST","name":"nutrition_eco","description":"Returns the nutritional values per hundred grams, the Nutri-Score and NOVA processing group, the environmental score where available, and the packaging composition, each with the data that produced it. A Nutri-Score without its inputs is a grade without a calculation: fibre and the fruit and vegetable share move the result substantially, and when they are absent the score is computed from what remains without that being visible in the grade itself. The response therefore lists the values that fed the score and names the ones that were missing, so a grade resting on half the inputs can be recognised. Serving size and per-serving values are returned separately from per-hundred-gram values rather than converted between them, since the serving size itself is frequently a manufacturer estimate. Environmental scores are returned as the record holds them without recomputation, and their absence for most products is stated rather than left as an empty field.","summary":"Bundle nutrition values, Nutri-Score, environmental and packaging data for a product — together with the inputs each score was computed from and which of them were missing.","inputSchema":{"type":"object","required":["barcode"],"additionalProperties":false,"properties":{"barcode":{"type":"string","minLength":8,"maxLength":20}}},"mimeType":"application/json","accepts":[{"scheme":"exact","network":"eip155:8453","payTo":"0x2880EdfFF13100677Bf97A3CBdF3Bc34771C4E5E","price":{"amount":"5000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","extra":{"asset":"USDC","network_name":"Base Mainnet","name":"USD Coin","version":"2","assetTransferMethod":"eip3009","eip712Domain":{"name":"USD Coin","version":"2","chainId":8453,"verifyingContract":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"}}},"maxTimeoutSeconds":300}]},{"url":"https://handel.halowerk.com/v1/reformulation-detector","method":"POST","name":"reformulation_detector","description":"A monitor with memory over food products. The first call stores a snapshot and says so rather than reporting everything as new. Later calls compare and report differences in the ingredient text, the allergen and trace lists, the additives, the nutritional values, the quantity, the serving size and the packaging. The distinction that decides whether a finding is worth anything is between a reformulation and a data entry: when a volunteer adds an ingredient that was previously missing, a naive comparison reports it as a recipe change. The completeness of the record is therefore compared alongside, and when it rises the change is flagged as probably an entry improvement rather than a product change. Both readings are given rather than one being chosen, because from outside they are not always separable. Allergen changes are reported separately from other changes since they are the ones with immediate consequences. Up to twenty-five products per call.","summary":"Watch products and report what changed since your last check — ingredients, allergens, nutrition, quantity and packaging — separating an actual reformulation from somebody merely filling in a missing field.","inputSchema":{"type":"object","required":["barcodes"],"additionalProperties":false,"properties":{"barcodes":{"type":"array","minItems":1,"maxItems":25,"items":{"type":"string","minLength":8,"maxLength":20}},"snapshot_token":{"type":"string","maxLength":80}}},"mimeType":"application/json","accepts":[{"scheme":"exact","network":"eip155:8453","payTo":"0x2880EdfFF13100677Bf97A3CBdF3Bc34771C4E5E","price":{"amount":"6000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","extra":{"asset":"USDC","network_name":"Base Mainnet","name":"USD Coin","version":"2","assetTransferMethod":"eip3009","eip712Domain":{"name":"USD Coin","version":"2","chainId":8453,"verifyingContract":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"}}},"maxTimeoutSeconds":300}]},{"url":"https://handel.halowerk.com/v1/hs-classify","method":"POST","name":"hs_classify","description":"Takes a product description and returns ranked tariff classification candidates. The first six digits are the WCO Harmonized System and are valid worldwide, including the EU. Digits 7-10 come from the UK Trade Tariff and are NOT the EU CN subheadings — they are returned as uk_commodity_code and must not be used for an EU customs declaration. This is a research aid, not a legally binding classification: only a Binding Tariff Information ruling (BTI in the EU, ATaR in the UK) binds customs. No duty rates are returned here — use /v1/landed-cost with a confirmed code for that. Candidates can be empty when the description is too generic; the response then says so instead of guessing.","summary":"Suggest HS and commodity code candidates for a plain-text product description, ranked with the matched terms and the official heading text.","inputSchema":{"type":"object","required":["description"],"additionalProperties":false,"properties":{"description":{"type":"string","minLength":3,"maxLength":300,"description":"Plain-text product description, e.g. \"stuffed plush toy bear, polyester\"."},"material":{"type":"string","maxLength":120,"description":"Main material, if known. Often decisive for the heading."},"intended_use":{"type":"string","maxLength":120,"description":"Intended use, e.g. \"promotional giveaway\", \"children under 3\"."},"max_results":{"type":"integer","minimum":1,"maximum":10,"default":5}}},"mimeType":"application/json","accepts":[{"scheme":"exact","network":"eip155:8453","payTo":"0x2880EdfFF13100677Bf97A3CBdF3Bc34771C4E5E","price":{"amount":"3000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","extra":{"asset":"USDC","network_name":"Base Mainnet","name":"USD Coin","version":"2","assetTransferMethod":"eip3009","eip712Domain":{"name":"USD Coin","version":"2","chainId":8453,"verifyingContract":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"}}},"maxTimeoutSeconds":300}]},{"url":"https://handel.halowerk.com/v1/recall-check","method":"POST","name":"recall_check","description":"Screens a product or supplier against the EU Safety Gate rapid alert system for dangerous non-food products. Matches on brand, product name, barcode/GTIN, category and country of origin. Returns each alert with case number, risk type, the hazard description, the measures ordered, the notifying member state and a link to the official alert page, plus aggregate counts by risk type and year for the brand. Limits: only cases notified by national market surveillance authorities are covered — an empty result is NOT a certificate of compliance and never presented as one. Coverage starts at the index year given in the response. Brand matching is normalised but not fuzzy, so a differently spelled brand can be missed. This is not legal advice and does not replace a conformity assessment, CE marking check or supplier audit.","summary":"Check a brand, product name or GTIN against EU Safety Gate (RAPEX) dangerous-product alerts and return the matching cases with risk type and measures taken.","inputSchema":{"type":"object","additionalProperties":false,"properties":{"brand":{"type":"string","maxLength":120,"description":"Brand or manufacturer name."},"product":{"type":"string","maxLength":200,"description":"Product name or free-text description."},"gtin":{"type":"string","maxLength":20,"description":"Barcode / GTIN / EAN, digits only."},"category":{"type":"string","maxLength":80,"description":"Safety Gate category, e.g. \"Toys\", \"Cosmetics\"."},"country_of_origin":{"type":"string","maxLength":60,"description":"Country of origin as named in the alerts, e.g. \"China\"."},"since":{"type":"string","maxLength":10,"description":"Only alerts published on or after this date, YYYY-MM-DD."},"risk_level":{"type":"string","enum":["any","serious"],"default":"any"},"limit":{"type":"integer","minimum":1,"maximum":50,"default":20}}},"mimeType":"application/json","accepts":[{"scheme":"exact","network":"eip155:8453","payTo":"0x2880EdfFF13100677Bf97A3CBdF3Bc34771C4E5E","price":{"amount":"3000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","extra":{"asset":"USDC","network_name":"Base Mainnet","name":"USD Coin","version":"2","assetTransferMethod":"eip3009","eip712Domain":{"name":"USD Coin","version":"2","chainId":8453,"verifyingContract":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"}}},"maxTimeoutSeconds":300}]},{"url":"https://handel.halowerk.com/v1/sanctions-check","method":"POST","name":"sanctions_check","description":"Checks a name against the European Commission Financial Sanctions Database — the consolidated list of persons, groups and entities subject to EU financial sanctions. Returns each match with the EU reference number, subject type, sanctions programme, the regulation that designated the entry, a link to the Official Journal text, plus published aliases, citizenships, dates of birth, addresses and identification documents where the list carries them. Every match states how it was found: exact, all-words, or partial. LIMITS, and they are not incidental: this covers the EU list only — not OFAC/SDN, not UK OFSI, not national lists, and not the UN list as a separate source. It does NOT apply the ownership and control test (the 50 percent rule), so subsidiaries of designated owners are not surfaced. There is no phonetic or transliteration matching beyond the aliases the Commission publishes, so a differently romanised name can be missed. A result with no match is NOT clearance and is never labelled as such. This is a first-pass research aid, not a compliance decision, and not legal advice.","summary":"Screen a person or company name against the EU consolidated financial sanctions list and return every matching designation with programme, legal basis and the published aliases.","inputSchema":{"type":"object","required":["name"],"additionalProperties":false,"properties":{"name":{"type":"string","minLength":2,"maxLength":200,"description":"Person or company name to screen, e.g. \"Ivan Petrov\" or \"Example Trading LLC\"."},"subject_type":{"type":"string","enum":["any","person","enterprise"],"default":"any","description":"Restrict to natural persons or to entities."},"programme":{"type":"string","maxLength":20,"description":"Restrict to a sanctions programme code, e.g. \"RUS\", \"IRQ\", \"SYR\"."},"match":{"type":"string","enum":["exact","all_words","partial"],"default":"all_words","description":"exact = normalised string equality. all_words = every significant word of the query appears in the alias. partial = at least one significant word, widest and noisiest."},"limit":{"type":"integer","minimum":1,"maximum":50,"default":20}}},"mimeType":"application/json","accepts":[{"scheme":"exact","network":"eip155:8453","payTo":"0x2880EdfFF13100677Bf97A3CBdF3Bc34771C4E5E","price":{"amount":"4000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","extra":{"asset":"USDC","network_name":"Base Mainnet","name":"USD Coin","version":"2","assetTransferMethod":"eip3009","eip712Domain":{"name":"USD Coin","version":"2","chainId":8453,"verifyingContract":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"}}},"maxTimeoutSeconds":300}]},{"url":"https://handel.halowerk.com/v1/sanctions-ofac","method":"POST","name":"sanctions_ofac","description":"Checks a name against the Specially Designated Nationals and Blocked Persons List published by the US Treasury Office of Foreign Assets Control. Returns each hit with the OFAC record number, the record type (individual, entity, vessel, aircraft), every sanctions programme the record is listed under, the aliases OFAC publishes together with their a.k.a./f.k.a./n.k.a. kind and OFAC's own strong/weak quality flag, plus nationalities, citizenships, dates and places of birth, addresses, identification documents and vessel particulars where the list carries them. Every hit states how it was found: exact, all_words or partial. LIMITS, and they are not incidental: this covers the SDN list ONLY. It does NOT cover OFAC's other sanctions lists — the Consolidated (non-SDN) lists such as SSI, CAPTA, NS-MBS, FSE and PLC are out of scope, so a party subject to sectoral or correspondent-account restrictions can be absent here. It does NOT apply OFAC's 50 Percent Rule: entities owned 50 percent or more, directly or indirectly, by one or more blocked persons are blocked by operation of law even though OFAC does not list them, and this endpoint will not surface them. There is no phonetic or transliteration matching beyond the aliases OFAC publishes, so a differently romanised name can be missed. OFAC marks some aliases \"weak\" precisely because they generate false positives; they are included by default and can be excluded. This is not the EU, UK or UN list. A result with no hit is NOT clearance and is never labelled as such. This is a first-pass research aid, not a compliance decision, and not legal advice.","summary":"Screen a person, company, vessel or aircraft name against the US OFAC Specially Designated Nationals (SDN) list and return every matching designation with its sanctions programmes, aliases and identifying details.","inputSchema":{"type":"object","required":["name"],"additionalProperties":false,"properties":{"name":{"type":"string","minLength":2,"maxLength":200,"description":"Person, company, vessel or aircraft name to screen, e.g. \"Ramzan Kadyrov\" or \"Example Trading LLC\"."},"record_type":{"type":"string","enum":["any","individual","entity","vessel","aircraft"],"default":"any","description":"Restrict to one OFAC record type."},"program":{"type":"string","maxLength":40,"description":"Restrict to an OFAC sanctions programme code, e.g. \"RUSSIA-EO14024\", \"IRAN\", \"SDGT\", \"CUBA\"."},"match":{"type":"string","enum":["exact","all_words","partial"],"default":"all_words","description":"exact = normalised string equality. all_words = every significant word of the query appears in the OFAC name. partial = at least one significant word, widest and noisiest."},"include_weak_aliases":{"type":"boolean","default":true,"description":"Include aliases OFAC itself flags as \"weak\". They are the main source of false positives; set false for a stricter sweep."},"limit":{"type":"integer","minimum":1,"maximum":50,"default":20}}},"mimeType":"application/json","accepts":[{"scheme":"exact","network":"eip155:8453","payTo":"0x2880EdfFF13100677Bf97A3CBdF3Bc34771C4E5E","price":{"amount":"4000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","extra":{"asset":"USDC","network_name":"Base Mainnet","name":"USD Coin","version":"2","assetTransferMethod":"eip3009","eip712Domain":{"name":"USD Coin","version":"2","chainId":8453,"verifyingContract":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"}}},"maxTimeoutSeconds":300}]},{"url":"https://handel.halowerk.com/v1/sanctions-ofsi","method":"POST","name":"sanctions_ofsi","description":"Checks a name against the UK Sanctions List maintained by the Foreign, Commonwealth and Development Office. Returns each hit with the UK designation ID, the legacy OFSI group ID, the UN reference where the designation mirrors a UN listing, the designation type (individual, entity, ship), the regime regulations under which it was made, whether the designation originates from the UK or the UN, the specific measures imposed (asset freeze, travel ban, trust services, director disqualification and others), the designation and last-updated dates, the UK statement of reasons, plus published aliases, nationalities, positions, dates and places of birth, addresses, documents, corporate and ship particulars where the list carries them. Every hit states how it was found: exact, all_words or partial. IMPORTANT ON SOURCE: the OFSI Consolidated List of Financial Sanctions Targets closed on 28 January 2026 and is no longer updated; the UK Sanctions List is now the single authoritative source, and it is what this endpoint carries. The legacy OFSI group ID is returned so existing references still resolve. LIMITS, and they are not incidental: this covers the UK list only — not the EU consolidated list, not OFAC/SDN, and not the UN list as a separate source. It does NOT apply the ownership and control test, so a company owned or controlled by a designated person is caught by UK law but is not on the list and is not surfaced here. Non-Latin-script spellings are stored and returned but are NOT matchable, and there is no phonetic or transliteration matching beyond the aliases the FCDO publishes, so a differently romanised name can be missed. This endpoint does not cover UK trade, transport or immigration sanctions beyond what the designation record itself states. A result with no hit is NOT clearance and is never labelled as such. This is a first-pass research aid, not a compliance decision, and not legal advice.","summary":"Screen a person, company or ship name against the UK Sanctions List — the successor to the OFSI consolidated list — and return every matching designation with its regime, the measures imposed and the published aliases.","inputSchema":{"type":"object","required":["name"],"additionalProperties":false,"properties":{"name":{"type":"string","minLength":2,"maxLength":200,"description":"Person, company or ship name to screen, e.g. \"Ramzan Kadyrov\" or \"Example Trading LLC\"."},"designation_type":{"type":"string","enum":["any","individual","entity","ship"],"default":"any","description":"Restrict to one UK designation type."},"regime":{"type":"string","maxLength":80,"description":"Restrict to designations whose regime name contains this text, e.g. \"Russia\", \"Iran\", \"Global Human Rights\"."},"origin":{"type":"string","enum":["any","uk","un"],"default":"any","description":"Restrict by where the designation comes from. uk = UK-originated, un = mirrors a UN listing. Designations marked \"UK|UN\" match both."},"match":{"type":"string","enum":["exact","all_words","partial"],"default":"all_words","description":"exact = normalised string equality. all_words = every significant word of the query appears in the listed name. partial = at least one significant word, widest and noisiest."},"limit":{"type":"integer","minimum":1,"maximum":50,"default":20}}},"mimeType":"application/json","accepts":[{"scheme":"exact","network":"eip155:8453","payTo":"0x2880EdfFF13100677Bf97A3CBdF3Bc34771C4E5E","price":{"amount":"4000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","extra":{"asset":"USDC","network_name":"Base Mainnet","name":"USD Coin","version":"2","assetTransferMethod":"eip3009","eip712Domain":{"name":"USD Coin","version":"2","chainId":8453,"verifyingContract":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"}}},"maxTimeoutSeconds":300}]}]}