Skip to content
agovena.
agovena.
Get started
Community

Developer guides

API overview

The current v1 endpoint map, catalog and account schemas, request examples, and error conventions.

API overview

Explore every operation

Choose an operation to see its request, response shape, access rules and implementation source.

On this page

Base URL and contract

The customer/storefront API lives at https://<your-shop>/api/v1. This documentation page is /development/api; it is not an API proxy. Use HTTPS and send Accept: application/json. For JSON writes also send Content-Type: application/json.

The route source is routes/api.php. The code also registers GET /api/v1/openapi.json, returning OpenAPI 3.0.3 from OpenApiDocument. That document describes operations, security, and selected request fields. It does not contain complete resource schemas and it is not proof that a Module is enabled on an installation. v1 is explicitly an early interface, not a frozen public contract.

bash
curl 'https://shop.example.test/api/v1/openapi.json' \
  --header 'Accept: application/json'

All example domains, names, IDs, tokens, and product slugs below are illustrative. Substitute values returned by your installation. Examples show response shapes, not captured production responses.

Endpoint collection

Paths in these tables are relative to /api/v1. Each method is grouped so you can scan the page like an API client collection. “Public” means the route does not require auth:sanctum; installation and other global middleware still apply. Ability names apply to bearer tokens. See authentication for sessions and token creation.

GET · Read

Method Path Access Request / response
GET /openapi.json Public OpenAPI document
GET /products Public q, category, page; paginated products
GET /products/{slug} Public Product by slug
GET /categories Public Category collection
GET /categories/{slug} Public Category and paginated products
GET /search Public q; up to eight product suggestions
GET /me account.read Account resource
GET /addresses addresses.read Address collection
GET /cart Public cart context Cart and X-Cart-Token response header
GET /checkout/requirements Public cart context Requirements and available payment methods
GET /orders orders.read Paginated orders
GET /orders/{order} orders.read Owned order
GET /invoices invoices.read Paginated invoices
GET /invoices/{invoice} invoices.read Owned invoice
GET /credit-notes credit_notes.read Paginated credit notes
GET /credit-notes/{creditNote} credit_notes.read Owned credit note
GET /support-tickets tickets.read Paginated support tickets
GET /support-tickets/{ticket} tickets.read Owned ticket summary

POST · Create or trigger

Method Path Access Request / response
POST /auth/tokens Email and password Named token; explicit abilities recommended
POST /addresses addresses.create Complete address; address resource
POST /cart Public cart context product_id, optional quantity and selections
POST /checkout orders.create Billing and checkout input; order resource
POST /orders/{order}/pay orders.pay Gateway and redirect URLs; payment attempt

PATCH · Update

Method Path Access Request / response
PATCH /me account.update Required name; account resource
PATCH /addresses/{address} addresses.update Complete address; address resource
PATCH /cart/{lineKey} Public cart context Quantity from 0 to 99; updated cart

DELETE · Revoke or remove

Method Path Access Request / response
DELETE /auth/tokens tokens.revoke Revoke current token; {"ok":true}
DELETE /addresses/{address} addresses.delete {"ok":true}
DELETE /cart/{lineKey} Public cart context Updated cart

The collection above reflects the current Core route source. Core has no public v1 routes to create products, change invoice status, issue refunds, create support tickets, administer packages, or expose a PUT operation. For cart, checkout, and payment request schemas use Cart and checkout API. Financial, ticket, and optional Module response fields are defined in Commerce API resources.

Catalog queries

GET /products selects active products, sorts by name, and paginates at 24 items. The q filter searches name or description only when its trimmed length is at least two characters. category accepts a category slug or ID. There is no controller option for page size or arbitrary sorting.

GET /products/{slug} selects an active product by slug, not numeric ID. Missing or inactive products return 404.

GET /search?q=... returns at most eight products, not a paginator. A query shorter than two trimmed characters returns an empty collection. The suggestion service also constrains products to available capabilities. Do not assume that every catalog action uses an identical query internally.

bash
curl --get 'https://shop.example.test/api/v1/products' \
  --header 'Accept: application/json' \
  --data-urlencode 'q=lamp' \
  --data-urlencode 'category=lighting' \
  --data-urlencode 'page=1'

curl 'https://shop.example.test/api/v1/products/reading-lamp' \
  --header 'Accept: application/json'

curl --get 'https://shop.example.test/api/v1/search' \
  --header 'Accept: application/json' --data-urlencode 'q=lamp'

Product schema

A single product is wrapped in data. The list returns data as an array, plus Laravel pagination links and meta.

Field Shape
id, name, slug Integer ID and strings
subtitle, sku, description Product text; nullable where not configured
price {amount: integer, currency: string, formatted: string}
category null or {id, name, slug}
images Array of public image URL strings
capabilities Array of capability keys
options Active options: {key, label, type, required, choices}
options[].choices Active choices: {value, label}

Amounts are integer minor units. Use the amount and currency for calculations, not the formatted display string. options is a selection contract, not a client-authoritative price quote.

Category schema

GET /categories returns data: Category[]. A Category contains id, name, slug, nullable image, integer products_count, and children. Each loaded child contains id, name, slug, and products_count; this is not an arbitrary-depth nested Category serializer.

GET /categories/{slug}?page=1 returns a different envelope:

json
{
  "data": {
    "category": {
      "id": 7,
      "name": "Lighting",
      "slug": "lighting",
      "image": null,
      "products_count": 0,
      "children": []
    },
    "products": []
  },
  "meta": {"current_page": 1, "last_page": 1, "total": 0}
}

The category detail action selects an active category and paginates its active products at 24 items. It returns only the shown pagination metadata, not the full Laravel resource links envelope.

Sources: CatalogController, ProductResource, CategoryResource, and SuggestStorefrontProducts.

Current account

GET /me and PATCH /me return:

json
{
  "data": {
    "id": 12,
    "name": "Alex Example",
    "email": "[email protected]",
    "email_verified": true
  }
}

PATCH accepts only the required name string, maximum 255 characters. It does not expose email changes, password changes, roles, or arbitrary customer properties.

bash
curl --request PATCH 'https://shop.example.test/api/v1/me' \
  --header "Authorization: Bearer $AGOVENA_TOKEN" \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --data '{"name":"Alex Example"}'

Address requests and responses

POST and PATCH share the same validation. PATCH is not a partial address patch: it still requires name, line1, city, postal_code, and country.

Field Rule
name, line1 Required string, maximum 255
city Required string, maximum 120
postal_code Required string, maximum 20
country Required string, exactly two characters
label Nullable string, maximum 80
company, line2 Nullable string, maximum 255
region Nullable string, maximum 120
phone Nullable string, maximum 40
is_default_billing, is_default_shipping Optional boolean
properties Nullable array with the supported address aliases

The supported properties keys are phone, company_name, address, address2, city, state, zip, and country. Their lengths match the equivalent top-level fields; properties.country is also checked against CheckoutCountries::codes(). If provided, these aliases take precedence when building the saved address. Required top-level fields remain required.

bash
curl --request POST 'https://shop.example.test/api/v1/addresses' \
  --header "Authorization: Bearer $AGOVENA_TOKEN" \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --data '{"label":"Office","name":"Alex Example","line1":"Example Street 1","city":"Brussels","postal_code":"1000","country":"BE","is_default_billing":true}'

An Address resource contains id, label, the address fields above, both default flags, and a properties object with those aliases. GET /addresses orders saved addresses by descending ID. If none exist, it may return an address reconstructed from customer properties, with id: null, default billing true, and default shipping false. Such an entry is not a stored address ID that can be patched or deleted.

Foreign address IDs return 404. Setting a saved address as a default clears that default flag on the customer's other saved addresses. POST currently returns a refreshed resource rather than explicitly setting an HTTP creation status; do not use the descriptive OpenAPI 201 entry as the sole runtime assertion.

Sources: AccountController, AddressResource, and SaveCustomerAddress.

Error envelope

Expected API errors use top-level message and code, with optional field errors:

json
{
  "message": "<localized validation message>",
  "code": "validation_error",
  "errors": {"name": ["<localized field error>"]}
}
HTTP status Typical code Client action
401 unauthenticated Supply valid authentication
403 unauthorized, insufficient_scope, ip_not_allowed Check ownership context, scope, and IP policy
404 not_found Check identifier, visibility, ownership, or enabled Module
409 invalid_state Reload state before trying again
422 validation_error, invalid_state, payment_failed Correct input or resolve the domain condition
429 rate_limited Back off rather than immediately replaying writes

errors is omitted when empty. Do not parse localized messages as stable identifiers. Exception type affects the code: validation exceptions map to validation_error, while a generic HTTP 422 maps to invalid_state. Unexpected server failures are not a guaranteed business-error schema.

Sources: ApiError, exception rendering, and StorefrontApiTest.

Search documentation

Search guides, commands and API endpoints

What are you looking for?

Documentation