API Client: Querying data out of an endpoint
In the request method the exception variable really doesn't have to
be set before using it, just inline it and make the code more succinct:

def request(self, endpoint, params=None):
    response = self.session.get(endpoint, timeout=TIMEOUT, params=params)
    res_code = response.status_code
    if res_code != API_OK:
        raise API_ERRORS[res_code]
    return response.json()


Also, I'm guessing API_ERRORS[res_code] will also work and be more
expected for any reader.

In the query_match method res doesn't have to be initialised, that's
not pythonic actually:

def query_match(self, match_id, shard='default'):
    url = f'{SHARD_URL}/{shard}/matches/{match_id}'
    return Match(self.request(url))


The process_matches method could be a bit simpler:

def process_matches(self, list_matches):
    ret = []
    for m_i in list_matches:
        ret.append(build_json(self.query_match(m_id)))
    mongo.insert_many('matches', ret)


Or, there's the option to go for a less imperative list comprehension
too:

def process_matches(self, list_matches):
    ret = [build_json(self.query_match(m_id))
           for m_i in list_matches]] 
    mongo.insert_many('matches', ret)


Regarding your second question, if I read it right, no, not a good idea
from what I can tell from the code, leaving Match as a pure data
object will serve you better in the long run.  It's better if the two
responsibilities aren't mixed.  It'll also make it more clear what's
being tested in your test cases if you can clearly distinguish between
something that just holds the data and a API client (wrapper) that does
networking (for example).