generated: '2026-08-17'
method: derived
source: json-schema/aramisauto-catalog-search-request.schema.json, json-schema/aramisauto-catalog-search-response.schema.json,
json-schema/aramisauto-catalog-base.schema.json, probe of https://api.aramisauto.com/
note: >-
Aramisauto publishes no API design guide, style guide or developer
documentation of any kind. Every convention below is DERIVED from the ten JSON
Schema 2020-12 documents it does publish at https://schemas.aramis.group/, or
PROBED from the live api.aramisauto.com challenge response. Nothing here is
taken from prose: where a convention is not observable in the schemas it is
recorded as `unknown`, not guessed. Idempotency, rate-limit signalling,
request-id tracing and versioning are all genuinely absent from the published
contracts — see the `absent` block — so no `Idempotency` pointer is wired in
apis.yml.
scope: >-
The Aramis Group vehicle catalog contracts (search + vehicle read/write model)
and the marketplace partner-feed configuration contracts.
auth:
style: ws-security-usernametoken
transport: https
observed_at: https://api.aramisauto.com/
evidence:
http_status: 403
body: Missing WSSE Username.
documented_by_provider: false
note: >-
The API vhost demands a WSSE (OASIS WS-Security UsernameToken) credential.
See authentication/aramisauto-authentication.yml. No public route to obtain
one is published.
pagination:
style: limit-offset
request_params:
- name: limit
type: integer
minimum: 0
default: 100
- name: offset
type: integer
minimum: 0
default: 0
response_fields:
- total
- limit
- offset
required_in_response:
- total
- limit
- offset
- vehicles
- facets
cursor: false
link_header: false
note: >-
Classic offset pagination. The response echoes the effective limit and offset
back alongside an absolute `total`, so a client can compute the last page
without a link header. Derived from search-request/search-response.
sparse_fields:
supported: true
param: fields
style: array-of-enumerated-dotted-paths
unique_items: true
examples:
- vin
- offerId
- offerType.id
- offerType.label
- mileage.km
- belgianOtoto.url
note: >-
`fields[]` is a CLOSED enum in the schema, not a free-form projection: the
caller may only ask for paths the contract already names. Dotted paths
address nested members (offerType.id vs offerType.label), so id and label
can be selected independently.
faceting:
supported: true
param: facets
style: array-of-enumerated-facet-names
unique_items: true
facet_count: 20
facets:
- offerType
- firstCirculationYear
- mileage.km.slice
- euronorm
- critair
- sellingPriceWithTaxes.slice
- sellingPriceWithTakeOverWithTaxes.slice
- indicativeLoadInstallment.slice
- maker
- model
- simpleColor
- simpleEquipment
- category
- segment
- energyType
- transmission
- drive
- promotion
- doors
- seats
response_shape: 'facets[]: [{ : [{ value: {id,label}, count: }] }]'
note: >-
Aggregations are opt-in per request. Numeric facets are served pre-bucketed
(`.slice` suffix) rather than as raw histograms.
filtering:
style: named-predicate-objects-under-criteria
predicate_count: 24
operators:
- operator: in
shape: '{ "in": [, ...] }'
applies_to: enumerated and identifier fields (offerType.id, maker, model, simpleColor.id,
simpleEquipment.id, category.id, energyType.id, transmission.id, drive.id, critair,
euronorm, promotion.id, offerId, vehicleId)
- operator: min/max
shape: '{ "min": , "max": }'
applies_to: range fields (firstCirculationDate, milage.km, sellingPriceWithTaxes,
sellingPriceWithTakeOverWithTaxes, indicativeMinimumMonthlyInstallment, indicativeMinimumMonthlyInstallmentWithTakeover,
doors, seats)
- operator: text
shape: '{ "text": "" }'
applies_to: whole-document free-text search
null_semantics: >-
An explicit null on either side of a min/max pair means "unbounded on that
side" — the provider's own example sends {"min": 12300, "max": null}.
strictness: additionalProperties is false at the request root, so unknown query
members are rejected rather than ignored.
sorting:
param: order
style: ordered-array-of-single-key-objects
shape: '[{ "": "asc"|"desc" }, ...]'
multi_key: true
sortable_fields:
- publicationDate
- mileage.km
- sellingPriceWithTaxes
- sellingPriceWithTakeOverWithTaxes
- indicativeMinimumMonthlyInstallment
- indicativeMinimumMonthlyInstallmentWithTakeover
- maker
- model
- power.ch
- combinedCycleConsumption.ltPer100Km
- combinedCycleConsumption.kwhPer100Km
note: >-
An ARRAY of single-key objects rather than a map, which is how the contract
preserves sort precedence in JSON.
identifiers:
keys:
- name: vin
type: string
pattern: ^[A-HJ-NPR-Z0-9]{17}$
note: 17-character ISO 3779 VIN, excluding I/O/Q. Nullable.
- name: offerId
type: string
note: The commercial offer. The unit a buyer transacts on.
- name: vehicleId
type: string
note: The physical/technical vehicle. One offer can carry several via variants[].
- name: aramisautoSupplierId
type: integer
note: Marketplace partner identity, assigned by Aramisauto.
- name: aramisautoPickupPointId
type: integer
note: Delivery/collection site, assigned by Aramisauto.
prefixes: none
format: opaque strings, no type prefix
value_objects:
convention: unit-bearing-nullable-objects
note: >-
The single strongest convention in these contracts: no bare numbers for
physical quantities. Every measurement is an object whose property NAMES the
unit, and the whole object is nullable so "unknown" is distinguishable from
zero. Defined once in base.schema.json and $ref'd everywhere.
units:
engineCapacity: cc
consumption: ltPer100Km | kwhPer100Km
co2Emissions: gramsPerKm
length: meters
weight: kg
volume: lt
speed: kmPerHour
distance: km
energy: kwh
power: kw
current: amperes
duration: minutes
percent: percent (0-100)
warrantyPeriod: km + years
enumerations:
convention: id-plus-label-pairs
note: >-
Controlled vocabularies are centralised in base.schema.json $defs and always
surface to clients as {id, label} — the id is the stable machine value, the
label is the localised display string. The searchable-data projection splits
them into parallel scalar fields (offer_type_id / offer_type_label) because
an index document cannot nest.
vocabularies:
offer-type-id:
- new
- used
- 0km
- nearly-new
status-id:
- available
- sold
- reserved
- available-soon
transmission-id:
- manual
- automatic
drive-id:
- fwd
- rwd
- 4wd
segment-id:
- company
- family
category-id:
- minivan
- mpv
- sedan
- station-wagon
- urban
- hatchback
- sport
- convertible
- suv
- van
energy-type-id:
- gasoline
- diesel
- electric
- biodiesel
- ethanol
- lpg
- cng
- hydrogen,
- hybrid
- full-hybrid
- hybrid-gasoline
- hybrid-diesel
euronorm-string: 1..6d-TEMP (Euro emissions standard)
critair-string: 0..5 (French Crit'Air air-quality certificate)
french-genre-string: CAM, CL, CTTE, CYCL, MAGA, MIAR, MTL, MTT1, MTT2, QM, REA,
REM, ... (French vehicle genre codes)
country-id: ISO 3166-1 alpha-3
defect:
field: energy-type-id
issue: >-
The enum value "hydrogen," carries a trailing comma inside the string. It is
reproduced verbatim in json-schema/ because these files are saved as
published; a client validating against the contract must send the comma.
Worth reporting to the provider.
naming:
request_and_read_models: camelCase with dotted paths for nested addressing
search_index_projection: snake_case (offer_id, offer_type_label, mileage_km_slice)
note: >-
Two deliberate naming registers: the API-facing models are camelCase, the
search-engine feed document is snake_case. A client that consumes both must
translate.
localisation:
strategy: multi-language input, single-language output
languages_named:
- fr
- es
- en
- nl
- de
note: >-
The write contract carries all languages; the read contract and the search
index are resolved to one. The five languages are enumerated in the
marketplace collect schema and match the Aramis Group markets.
error_envelope:
observed: true
format: xml-error-list
media_type: application/xml; charset=utf-8
shape: ...
observed_at: https://api.aramisauto.com/
observed_status: 403
observed_message: Missing WSSE Username.
rfc9457: false
problem_json: false
documented_by_provider: false
note: >-
Recorded from the wire, not from docs. The published JSON Schemas define NO
error shape at all — search-response has no error member — so the only error
contract observable for Aramisauto is this XML envelope returned by the
gateway. One message is all an anonymous caller can see, which is why no
errors/ catalog artifact was written: a single probed challenge string is not
an error catalog.
absent:
- convention: idempotency
status: absent
detail: >-
No Idempotency-Key header, no idempotency scope, no retention window and no
request-deduplication field appears in any published schema or on any probed
response. The catalog contracts are read/ingest shaped and define no
client-supplied request key.
pointer_emitted: false
- convention: rate-limit-signalling
status: absent
detail: >-
No RateLimit-* / X-RateLimit-* headers and no Retry-After were returned by
any probed response, and no limits are published anywhere. See
rate-limits/aramisauto-rate-limits.yml.
- convention: request-id-tracing
status: partial
detail: >-
No documented correlation-id request header. The gateway does return
`x-apache-request` (e.g. aoMLGaCLd5vQkUz9bOgvsAAAAAA) and a Cloudflare
`cf-ray` on every response, which are usable for support correlation but are
server-assigned and undocumented.
- convention: versioning
status: absent
detail: >-
The schema $ids are unversioned (https://schemas.aramis.group/catalog/base.schema.json
with no /v1/ segment and no version member), and there is no published
versioning or deprecation policy. Consumers pin by git commit or not at all.
- convention: metadata-and-expansion
status: absent
detail: >-
No customer-defined metadata bag and no expand parameter. Related data is
embedded unconditionally (variants[], equipments[], options[], media[]) and
trimmed with fields[] instead.
cross_references:
authentication: authentication/aramisauto-authentication.yml
conformance: conformance/aramisauto-conformance.yml
data_model: data-model/aramisauto-data-model.yml
rate_limits: rate-limits/aramisauto-rate-limits.yml
schemas: json-schema/_index.yml