PHP Application layers
SQL injection

First of all, your PDO code is a straw plane that never flies. Using prepare() like that makes very little sense, leaving all your queries widely exposed to SQL injection attacks. 

prepare() doesn't protect your queries by itself, making them immune by means of some magic. It helps only if you take out every single variable from your query and substitute it with a placeholder, then prepare your query and then finally execute, adding variables separately.

Therefore, all methods in DSSql should be changed in order to accept two variables - a query and an array with data:

public function read($sql, $params = [])
{        
    $stmt=$this-&gt;bd-&gt;prepare($sql);
    $stmt-&gt;execute($params);
    $response = $stmt-&gt;fetch(PDO::FETCH_ASSOC);        
    return $response;
}


Code duplication

As you may notice, the code in DSSql class' methods is heavily duplicated. Why not to create a basic method to run an arbitrary query, an then call this method with only different return formats?

public function query($sql, $params = [])
{        
    $stmt=$this-&gt;bd-&gt;prepare($sql);
    $stmt-&gt;execute($params);
    return $stmt;
}

public function read($sql, $params = [])
{        
    return $this-&gt;query($sql, $params)-&gt;fetch(PDO::FETCH_ASSOC);
}

public function readAll($sql)
{
    return $this-&gt;query($sql)-&gt;fetchAll(PDO::FETCH_ASSOC);
}

public function save($sql, $params)
{
    return $this-&gt;query($sql, $params);
}


Existing PHP classes' code reuse

As you may notice, your methods now bear very little difference. Why not to take them out at all and make use of the powerful PDOSTatement class already exists in PHP? 

public function searchById($id)
{
    $sql = "SELECT  * FROM clients WHERE id=?";
    return $this-&gt;ds-&gt;query($sql, [$id])-&gt;fetch();
}

public function searchAll()
{
    $sql = "SELECT * FROM clients"; 
    return $this-&gt;query($sql)-&gt;fetchAll();
}


ORM

The code in the save() method is not really does the save but rater runs an arbitrary query, which could be quite confusing. If you want a real save, read and such methods, consider using an ORM, a class that constructs SQL queries for you, and in such a case it will be indeed save() or find() with no other meaning 

Questions


  Is correct to form queries at repository classes?


yes, it's the place where SQL belongs


  Where should I handle SQL errors? Having an SQLError


Wherever you are handling all other errors. There is nothing special in SQL errors, handle them the same way as others. 


  How should I handle access to APIs?


That is somewhat too wide question for a comment, especially without any context given. May be you should ask on Stack Overflow.


  As my app has role based access for users, how does this impacts my design/implementation? Based on logged user role I've create different classes using same interface but implementing different queries to database.


Well, this is somewhat a key question. Consider using an existing framework instead of rolling up a your own. Established frameworks already have all you need out of the box, including ORM, a template engine and of course a user management module with role based authorization. I would suggest Symfony as being the most popular PHP framework that encourages best coding practices.