Nicolas Dabene
Back to blog
12 September 2025 Nicolas Dabene 3 min

Contribute to PrestaShop 9 Admin API

Quick Start: Contributing Quickly to PrestaShop 9 Admin API

API PrestaShop development security
AI commerce

Quick Start: Contributing Quickly to PrestaShop 9 Admin API

Quick Start: Contributing Quickly to PrestaShop 9 Admin API

Mind map of 8 essential concepts for PrestaShop 9 Admin API

Contributing to PrestaShop 9’s new Admin API can seem intimidating. We read words like CQRS, API Platform, OAuth2… and many developers think:

“Wow, I’ll need to follow weeks of training before laying my first brick.”

Actually, it’s false ✅ With only 8 well-understood concepts, you can create a functional endpoint in less than an hour.

In this guide, I’ll explain each building block as if we were together in a classroom: I set the context, illustrate with a concrete example, then we move forward step by step.


1. #[ApiResource]: The Magic Label

Imagine a library. As long as a book doesn’t have a barcode, impossible to borrow it.

In PrestaShop, this barcode is #[ApiResource]. It tells API Platform: “This class is a resource exposed by the API.”

  • Without it → the class remains invisible
  • With it → it becomes a REST entry point

📚 Read official ApiResource doc


2. CQRSGet and CQRSCreate: Separating Reading and Acting

PrestaShop 9 applies a clear discipline:

  • Reading data → role of Queries
  • Modifying data → role of Commands

👉 This is the CQRS pattern (Command Query Responsibility Segregation).

Concretely:

  • CQRSGet → “When doing a GET, execute this Query.”
  • CQRSCreate → “When doing a POST, execute this Command, then return the result thanks to this Query.”

📚 Learn more about CQRS in PrestaShop


3. URI Templates: Your Resources’ Address

Each resource needs a readable and structured address.

<span class="s1">'/products/{productId}'</span>

➡️ Here, the API responds to /products/123 with 123 as parameter.

You can nest multiple levels:

/categories/{categoryId}/products/{productId}

👉 Think of it as a city map: your URIs are the streets where developers will navigate.

📚 Doc on API Resources


4. DTOs: Data Bags

A DTO (Data Transfer Object) = a backpack 🎒 It does nothing by itself, just transports data.

Minimalist example:

<span class="kd">class</span> <span class="nc">Product</span> <span class="p">{</span>
    <span class="k">public</span> <span class="kt">int</span> <span class="nv">$id</span><span class="p">;</span>
    <span class="k">public</span> <span class="kt">string</span> <span class="nv">$name</span><span class="p">;</span>
<span class="p">}</span>

No business logic here. 👉 All intelligence already lives in your Commands and Queries.


5. OAuth Scopes: Access Badges

An API is an open door. But who has the right to enter? The answer: OAuth2 scopes.

Each operation declares necessary permissions. Examples:

  • product_read → read products
  • product_write → modify products

See them as company access badges. Without the right badge → no entry.

📚 Admin API OAuth doc


6. Requirements: Filtering at the Door

An endpoint /products/{productId} must receive a numeric identifier. But what if someone sends /products/abc?

👉 Add a requirement:

<span class="n">requirements</span><span class="o">:</span> <span class="p">[</span><span class="s1">'productId'</span> <span class="o">=></span> <span class="s1">'\\d+'</span><span class="p">]</span>

Result: only URLs with a number (/products/123) are accepted. It’s the bouncer at the nightclub entrance: wrong outfit → no entry.


7. The Identifier: Your Resource’s ID Card

API Platform must know which field represents the unique identifier. Otherwise, impossible to properly manage your resources.

So we add:

<span class="c1">#[ApiProperty(identifier: true)]</span>
<span class="k">public</span> <span class="kt">int</span> <span class="nv">$id</span><span class="p">;</span>

Only one field must play this role. 👉 It’s your resource’s social security number.


8. Organization: One Folder per Entity

Last concept: a bit of discipline! In ps_apiresources, each resource lives in its folder:

ps_apiresources/src/ApiPlatform/Resources/Product/

👉 Like a well-organized backpack: one subject = one notebook, one resource = one folder.

📚 Explore ps_apiresources GitHub repo


Concrete Example: Product Resource

<span class="cp"><?php</span>
<span class="kn">namespace</span> <span class="nn">PrestaShop\Module\APIResources\ApiPlatform\Resources\Product</span><span class="p">;</span>

<span class="kn">use</span> <span class="nc">ApiPlatform\Metadata\ApiResource</span><span class="p">;</span>
<span class="kn">use</span> <span class="nc">ApiPlatform\Metadata\ApiProperty</span><span class="p">;</span>
<span class="kn">use</span> <span class="nc">PrestaShopBundle\ApiPlatform\Metadata\CQRSGet</span><span class="p">;</span>
<span class="kn">use</span> <span class="nc">PrestaShopBundle\ApiPlatform\Metadata\CQRSCreate</span><span class="p">;</span>

<span class="c1">#[ApiResource(</span>
    <span class="n">operations</span><span class="o">:</span> <span class="p">[</span>
        <span class="k">new</span> <span class="nc">CQRSGet</span><span class="p">(</span>
            <span class="n">uriTemplate</span><span class="o">:</span> <span class="s1">'/products/{productId}'</span><span class="p">,</span>
            <span class="n">requirements</span><span class="o">:</span> <span class="p">[</span><span class="s1">'productId'</span> <span class="o">=></span> <span class="s1">'\\d+'</span><span class="p">],</span>
            <span class="nc">CQRSQuery</span><span class="o">:</span> <span class="nc">GetProductForEditing</span><span class="o">::</span><span class="n">class</span><span class="p">,</span>
            <span class="n">scopes</span><span class="o">:</span> <span class="p">[</span><span class="s1">'product_read'</span><span class="p">]</span>
        <span class="p">),</span>
        <span class="k">new</span> <span class="nc">CQRSCreate</span><span class="p">(</span>
            <span class="n">uriTemplate</span><span class="o">:</span> <span class="s1">'/products'</span><span class="p">,</span>
            <span class="nc">CQRSCommand</span><span class="o">:</span> <span class="nc">AddProductCommand</span><span class="o">::</span><span class="n">class</span><span class="p">,</span>
            <span class="nc">CQRSQuery</span><span class="o">:</span> <span class="nc">GetProductForEditing</span><span class="o">::</span><span class="n">class</span><span class="p">,</span>
            <span class="n">scopes</span><span class="o">:</span> <span class="p">[</span><span class="s1">'product_write'</span><span class="p">]</span>
        <span class="p">)</span>
    <span class="p">]</span>
<span class="p">)]</span>
<span class="kd">class</span> <span class="nc">Product</span>
<span class="p">{</span>
    <span class="c1">#[ApiProperty(identifier: true)]</span>
    <span class="k">public</span> <span class="kt">int</span> <span class="nv">$productId</span><span class="p">;</span>

    <span class="k">public</span> <span class="kt">string</span> <span class="nv">$name</span><span class="p">;</span>
    <span class="k">public</span> <span class="kt">float</span> <span class="nv">$price</span><span class="p">;</span>
    <span class="k">public</span> <span class="kt">bool</span> <span class="nv">$active</span><span class="p">;</span>
<span class="p">}</span>


Tip: “Cheating” with Existing Commands and Queries

The secret? No need to reinvent everything: most Commands and Queries already exist in PrestaShop core!

To discover them:

php bin/console prestashop:list:commands-and-queries

Examples:

  • AddProductCommand / GetProductForEditing
  • AddCategoryCommand / GetCategoryForEditing
  • AddCustomerCommand / GetCustomerForEditing

📚 Official Commands/Queries list


How to Start Today?

  1. Join Slack #cfc-adminapi to ask your questions.
  2. Explore existing resources in ps_apiresources.
  3. Copy the template above, adapt it, propose a Pull Request.

Conclusion: Learning by Walking

Many hesitate to contribute because they believe they must master everything before starting. The truth: we learn by contributing.

With these 8 simple concepts, you already have the keys to write an endpoint. Advanced notions (State Providers, Processors, Serialization Groups…) will come naturally with practice.

👉 The best time to start was yesterday. The second best time is today.


🔗 Useful Resources


Article published on September 12, 2025 by Nicolas Dabène - PrestaShop Expert & open source contributor since 2010.

LinkedIn

Follow my AI and e-commerce analysis

I share practical notes on AI agents, PrestaShop architecture, MCP and automation for e-commerce teams.

Follow on LinkedIn