Le , João Paulo fait ses débuts professionnels lors d'un match du Gaúcho contre Ypiranga de Erechim(pt). Il entre sur le terrain à la 80e minute de jeu en remplaçant Wagner Libano[2]. À la fin de la saison, il remporte la Copa FGF(pt) avec la réserve[3]. Il dispute trois matchs pour sa première saison professionnelle. La saison suivante, il fait ses débuts en Série A contre l'Atlético Goianiense le . Il entre sur le terrain à la 88e minute de jeu en remplaçant Tinga[4]. Le , il dispute sa première rencontre en tant que titulaire en Série A contre l'Esporte Clube Bahia[5],[6].
Le , il prolonge son contrat de deux ans, ce qui le lie au club jusqu'en [7]. Le , il fait ses débuts en Copa Libertadores face au Once Caldas. Il entre sur le terrain à la 85e minute de jeu en remplaçant Oscar[8],[9].
Une succession de prêts
Le , João Paulo est prêté à l'Atlético Goianiense, qui vient d'être reléguer en deuxième division, afin d'engranger de l'expérience[10]. Le , il fait ses débuts en tant que titulaire lors d'un match du Goiano contre le Grêmio Anápolis[11] et délivre une passe décisive[12]. Trois jours plus tard, il inscrit son premier but chez les professionnels à l'occasion d'un match du Goiano contre Vila Nova FC[13]. Cependant, il perd la finale du championnat du Goiás contre Goiás Esporte Clube en deux matchs[14]. Puis, le , il fait ses débuts en tant que titulaire en Série B contre Palmeiras[15]. Lors de la 28e journée de Série B, il marque son premier doublée face à l'ASA[16],[17].
Le , João Paulo est de nouveau prêté mais à un échelon supérieur, en rejoignant le club du Goiás Esporte Clube en Série A[18]. Le , il fait ses débuts lors d'un match du Goiano contre Vila Nova FC. Il entre sur le terrain à la 62e minute de jeu en remplaçant Thiago Mendes[19]. Il perd pour la deuxième fois la finale du championnat du Goiás contre l'Atlético Goianiense en deux matchs, mais n'entre pas en jeu[20]. Il aura disputé treize rencontres dont cinq en Série A.
Santa Cruz FC
Le , João Paulo est prêté à Santa Cruz FC, qui évolue en Série B[21]. Le , il fait ses débuts en tant que titulaire lors d'un match du Pernambucano contre le Central Sport Club, où il marque son premier but durant cette rencontre[22]. Le , lors du clássico das Multidões(pt) contre le Sport Club do Recife, il égalise dans le temps additionnel[23]. Il gagne la finale du championnat du Pernambouc face à Salgueiro Atlético Clube(pt) en deux matchs[24]. Il est élu meilleur joueur et meilleur milieu de terrain du tournoi[25]. Puis, le , il fait ses débuts en tant que titulaire en Série B contre Macaé Esporte[26]. À la fin de la saison, le SCFC occupant la deuxième place de Série B, le club se voit promu en Série A[27].
João Paulo est transféré au Botafogo de Futebol e Regatas le et signe un contrat de trois ans[36]. Le montant du transfert est de trois millions de réaux (pour 60 % des droits du joueur et 40 % reste au profit de Santa Cruz)[37]. Il était proche de rejoindre le Botafogo la saison précédente[38]. Il est officiellement présenté le [39].
Le , il fait ses débuts pour Botafogo lors du deuxième tour préliminaire de la Copa Libertadores face au Colo-Colo. Il entre sur le terrain à la 46e minute de jeu en remplaçant Airton[40]. Au match retour contre le Colo-Colo, il dispute sa première rencontre en tant que titulaire avec Botafogo[41]. Il déviant un joueur clé pour son équipe[42]. Puis, le , il inscrit son premier but en Copa Libertadores contre le Club Nacional[43]. Le Botafogo est éliminée en quart de finale de la Copa Libertadores par le futur vainqueur, le Grêmio[44]. Au total, il inscrit un but et délivre deux passes décisives lors de cette compétition. Il inscrit un but et délivre une passe décisive le lors de la 25e journée de Série A contre le Coritiba FC[45].
Il prend part à treize matchs en début de saison 2018, avant de se blesser gravement à la jambe lors d'un match du Carioca face au Vasco da Gama le [46]. Victime d'une fracture du tibia et du péroné[47]. Opéré avec succès à la clínica São Vicente le lendemain[48], il devrait rester éloigné des terrains entre six mois et huit mois[49]. Le , il dispute sa première rencontre depuis sa blessure contre le Paraná Clube lors de l'avant-dernière journée du championnat[50].
Le , il prolonge son contrat de deux ans, ce qui le lie au club jusqu'en [51],[52]. Le , il dispute son premier match en tant que titulaire depuis sa blessure à la jambe[53], contre l'Associação Desportiva Cabofriense lors de la première journée du Carioca[54]. Le , il marque son premier but premier but de la saison face au Clube de Regatas do Flamengo[55], mais il sort sur blessure au bout de 37 minutes[56]. Il n'avait plus marqué en compétitions officielle depuis 1 an, 2 mois et 10 jours[Note 1]. Le , il est titulaire et joue 90 minutes pour la première fois depuis sa grave blessure contre l'Esporte Clube Bahia, lors de la deuxième journée de Série A[58]. Durant cette rencontre, il inscrit son deuxième but de la saison[59].
Le , il fait ses débuts en tant que titulaire pour les Sounders en Ligue des champions de la CONCACAF face au Club Deportivo Olimpia[64], où il marque son premier but durant cette rencontre[65]. Au match retour à Seattle, il inscrit un but et délivre une passe décisive mais s'incline aux tirs au but[66],[67]. Le , il participe à son premier match en Major League Soccer en tant que titulaire face au Fire de Chicago[68]. Après deux semaines d'activités dans la MLS, le championnat est suspendu en raison de la pandémie de Covid-19 aux États-Unis[69]. C’est dans ce contexte très particulier que les Sounders retrouvent les terrains quatre mois après, à l’occasion du tournoi nommé MLS is Back[70],[71], mais il ne participe à aucune rencontre du tournoi en raison d'une blessure[72],[73],[74]. Le , il inscrit son premier but en MLS face aux Earthquakes de San José[75],[76]. Puis le , il marque son deuxième but en MLS face aux Whitecaps de Vancouver[77],[78]. Lors de la finale de la Coupe MLS, il est titulaire lors de la défaite 3-0 face au Crew de Columbus[79],[80]. Il réalise une bonne saison[81]. Les Sounders et le Botafogo négocient pour le transfert définitif du Brésilien[82],[83], ce qui intervient le 21 janvier 2021 tout en conservant un statut de joueur désigné[84].