Aplicando HATEOAS em uma API JAX-RS \| TreinaWeb               Promoção no ar   Matricule-se agora e garanta **54% de desconto**  

  Termina em   Tempo restante da oferta: 13 Horas 

 17 Min 

 01 Seg 

   Tempo restante da oferta: 13 17 01 

  [Assinar →](https://www.treinaweb.com.br/checkout/pagamento/plano/anual?cupom=TW-SCLIENTE26) 

   [                ](https://www.treinaweb.com.br)  Explorar  

 [ Quanto custa? ](#assinatura) [ FAQ ](https://www.treinaweb.com.br#faq) [Matricule-se](#assinatura) [ Entrar ](https://www.treinaweb.com.br/login) 

     [ Início ](https://www.treinaweb.com.br) [ Artigos ](https://www.treinaweb.com.br/blog) Aplicando HATEOAS em uma API JAX-RS  [ Java ](https://www.treinaweb.com.br/blog/categoria/java) 

# Aplicando HATEOAS em uma API JAX-RS

 Veja como implementar o HATEOAS em uma aplicação JAX-RS-Jersey de forma simples com os recursos fornecidos por esta especificação.

 [ Wladimilson M. Nascimento ](https://www.treinaweb.com.br/blog/autor/wladimilson-m-nascimento) 6 anos atrás

  ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2020/07/aplicando-hateoas-em-uma-api-jax-rs.png)  

[HATEOAS](https://www.treinaweb.com.br/blog/o-que-e-hateoas/) (Hypermedia as the Engine of Application State) é um requisito da arquitetura REST, onde os recursos de uma API deve retornar nas suas respostas links (URI) que indicam como acessar outros recursos e/ou aplicar outras ações nos recursos acessados.

Desta forma, o client necessita conhecer apenas o endpoint principal da [API](https://www.treinaweb.com.br/blog/o-que-e-uma-api/) para poder navegar nela. Ao implementar HATEOAS, este endpoint e todos os demais irão retornar links que permitirá ao client explorar todos os recursos fornecidos.

Existem algumas formas de implementar este recurso em API JAX-RS, que veremos a seguir.

[  ![Java - Fundamentos de JAX-WS e JAX-RS](https://d2knvm16wkt3ia.cloudfront.net/assets/svg-icon/java.svg)   Curso Java - Fundamentos de JAX-WS e JAX-RS Conhecer o curso ](https://www.treinaweb.com.br/curso/java-fundamentos-de-jax-ws-e-jax-rs)

## HATEOAS no JAX-RS com UriBuilder e Link

Para a implementação do HATEOAS, o JAX-RS fornece duas classes: `UriBuilder` e `Link`. Como o nome sugere, a `UriBuilder` facilita a criação de uma URI, enquanto `Link` é uma representação de um recurso relacionado que atende a especificação RFC 5988.

Para compreendê-los, vamos ver um exemplo prático.

Neste artigo, utilizarei de exemplo a [API RESTful implementada em JAX-RS API](https://www.treinaweb.com.br/blog/criando-uma-api-restful-com-a-jax-rs-api/) já apresentada anteriormente. Como [ela implementa autenticação JWT](https://www.treinaweb.com.br/blog/implementando-autenticacao-baseada-em-jwt-em-uma-api-restful-jax-rs/), o seu ponto de entrada será o endpoint de login, que no momento retorna apenas o token de acesso:

```java
@POST
@Produces(MediaType.TEXT_PLAIN)
@Consumes(MediaType.APPLICATION_JSON)
public Response post(Usuario usuario)
{
    try{
        if(usuario.getUsuario().equals("teste@treinaweb.com.br") 
		   && usuario.getSenha().equals("1234"))
        {
            String jwtToken = Jwts.builder()
                .setSubject(usuario.getUsuario())
                .setIssuer("localhost:8080")
                .setIssuedAt(new Date())
                .setExpiration(
					Date.from(
						LocalDateTime.now()
						.plusMinutes(15L)
						.atZone(ZoneId.systemDefault())
						.toInstant()
					)
				)
                .signWith(CHAVE, SignatureAlgorithm.HS512)
                .compact();

            return Response.status(Response.Status.OK).entity(jwtToken).build();
        }
        else
            return Response
					.status(Response.Status.UNAUTHORIZED)
					.entity("Usuário e/ou senha inválidos")
					.build();
    }
    catch(Exception ex)
    {
        return Response
				.status(Response.Status.INTERNAL_SERVER_ERROR)
				.entity(ex.getMessage())
				.build();
    } 
}

```

A partir dele, ao ser autenticado, o client poderá acessar as pessoas cadastradas. Para indicar isso, podemos utilizar a classe `UriBuilder` para criar a URI deste endpoint:

```java
UriBuilder.fromUri("http://localhost:8080/")
        .path("pessoa")
        .build();

```

Este endpoint não define parâmetros, mas caso houve isso poderia ser indicado:

```java
UriBuilder.fromUri("http://localhost:8080/")
        .path("pessoa/{id}")
        .build(2);

```

Desta forma, a URI criada seria:

```java
http://localhost:8080/pessoa/2

```

Da mesma forma, também poderia ser adicionadas querystrings:

```java
UriBuilder.fromUri("http://localhost:8080/")
        .path("pessoa/{id}")
        .queryParam("q", "{nome}")
        .build(2, "Carlos");

```

Neste caso, a URI seria:

```java
http://localhost:8080/pessoa/2?q=Carlos

```

Para definir a URI do nosso endpoint, além da classe `UriBuilder`, faremos uso da classe `Link`:

```java
Link link = Link.fromUriBuilder(
                    UriBuilder.fromUri("http://localhost:8080/")
                    .path("pessoa")
                )
                .rel("lista_pessoas")
                .type("GET")
                .build();

```

Note que esta classe, além do `UriBuilder` , define a relação da URI com o endpoint atual (de login) e o tipo da solicitação.

Para que este dado seja retornado na resposta da solicitação, ele deve ser informado no método `link` da classe `Response`:

```java
return Response.status(Response.Status.OK).entity(jwtToken).links(link).build();

```

Ao fazer isso, esta informação estará no header da resposta:

![Enpoint Login com Hateoas retornado no header](https://dkrn4sk0rn31v.cloudfront.net/uploads/2020/07/hateoas-header-endpoint-login.png)

Este é o formato que a especificação RFC 5899 define. Porém este não é o usual, o client normalmente espera esta informação no corpo da resposta. Veremos como fazer isso conhecendo o recursos para HATEOAS do Jersey.

## Problemas do HATEOAS no corpo da resposta

Para que o link do HATEOAS também seja mostrado no corpo de uma resposta, é necessário que ele seja definido como um campo do recurso:

```java
public class Pessoa {
    private int id;
    private String nome;
    private int idade;
    private Link link;

    public Link getLink() {
        return link;
    }

    public void setLink(Link link) {
        this.link = link;
    }

    //..Código omitido
}

```

E ao retornar este recurso, este campo deve ser preenchido:

```java
@Authorize
@GET
@Path("{id}")
@Produces(MediaType.APPLICATION_JSON)
public Pessoa getById(@PathParam("id") int id) {
    Pessoa pessoa = _repositorio.Get(id);
    pessoa.setLink(
        Link.fromUriBuilder(
            UriBuilder.fromUri("http://localhost:8080/")
            .path("pessoa/{id}")
        )
        .rel("self")
        .type("GET")
        .build(id)
    );
    return pessoa;
}

```

Com isso, no corpo da resposta desta solicitação, o link será informado:

![Endpoint Pessoa com Hateoas com um link mostrando todas as propriedades da classe Link](https://dkrn4sk0rn31v.cloudfront.net/uploads/2020/07/hateoas-header-endpoint-pessoa.png)

Entretanto, um problema disso é que também são retornadas algumas informações indesejadas. Para que isso seja resolvido, é necessário alterar json provider para o Jackson:

```xml

    org.glassfish.jersey.media
    jersey-media-json-jackson

```

Registrá-lo:

```java
public static HttpServer startServer() {
    final ResourceConfig rc = new ResourceConfig().packages("br.com.treinaweb");
    rc.register(JacksonFeature.class);
    return GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), rc);
}

```

E por fim, criar um Adapter:

```java
public class LinkAdapter extends XmlAdapter {

    public LinkAdapter() {}

    public Link unmarshal(LinkJaxb p1) {
        Link.Builder builder = Link
                                .fromUri(p1.getUri())
                                .rel(p1.getRel())
                                .type(p1.getType());

        return builder.build();
    }

    public LinkJaxb marshal(Link p1) {
        return new LinkJaxb(
                        p1.getUri(), 
                        p1.getRel(), 
                        p1.getType()
                    );
    }
}

class LinkJaxb {

    private URI uri;
    private String rel;
    private String type;

    public LinkJaxb() {
        this(null, null, null);
    }

    public LinkJaxb(URI uri, 
                    String rel, 
                    String type) 
    {
        this.uri = uri;
        this.rel = rel;
        this.type = type;
    }

    @XmlAttribute(name = "href")
    public URI getUri() {
        return uri;
    }

    public void setUri(URI uri) {
        this.uri = uri;
    }

    @XmlAttribute(name = "rel")
    public String getRel(){
        return rel;
    }

    public void setRel(String rel) {
        this.rel = rel;
    }

    @XmlAttribute(name = "type")
    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }
}

```

Que deve ser informado no campo do recurso:

```java
@XmlJavaTypeAdapter(LinkAdapter.class)
private Link link;

```

Agora, o link retornado será mais amigável:

![Enpoint Pessoa com HATEOAS de um link amigável](https://dkrn4sk0rn31v.cloudfront.net/uploads/2020/07/hateoas-header-endpoint-pessoa-link.png)

Entretanto, até agora foi necessário definir “manualmente” o link do recurso. Imagine quando for uma lista, este procedimento será bem “chato”. Felizmente o Jersey tem a solução para este problema.

## HATEOAS no Jersey com @InjectLink

Para resolver o trabalho de criar um link individualmente para cada recurso, o Jersey fornece módulo Declarative Linking, que define anotação `@InjectLink`, que pode ser aplicada diretamente no campo `Link`:

```java
@InjectLink(
        resource = PessoaResource.class,
        style = Style.ABSOLUTE,
        rel = "self",
        bindings = @Binding(name = "id", value = "${instance.id}"),
        method = "GET"
)
@XmlJavaTypeAdapter(LinkAdapter.class)
private Link link;

```

Este módulo requer a dependência abaixo:

```xml

    org.glassfish.jersey.ext
    jersey-declarative-linking

```

Com isso não é necessário criá-lo manualmente:

```json
@Authorize
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Response post(Pessoa pessoa)
{
    try{
        _repositorio.Add(pessoa);
        return Response.status(Response.Status.CREATED).entity(pessoa).build();
    }
    catch(Exception ex)
    {
        return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(ex.getMessage()).build();
    } 
}

```

Pois será adicionado automaticamente pelo Jersey:

![Enpoint Pessoa com HATEOAS de um link amigável](https://dkrn4sk0rn31v.cloudfront.net/uploads/2020/07/hateoas-header-endpoint-pessoa-link.png)

Caso o recurso possua vários links, eles podem ser agrupados em uma lista:

```java
List links;

```

E esta lista pode receber a anotação `@InjectLinks`:

```java
@InjectLinks({
    @InjectLink(
        resource = PessoaResource.class,
        style = Style.ABSOLUTE,
        rel = "self",
        bindings = @Binding(name = "id", value = "${instance.id}"),
        method = "GET"
    ),
    @InjectLink(
            resource = PessoaResource.class,
            style = Style.ABSOLUTE,
            rel = "update",
            bindings = @Binding(name = "id", value = "${instance.id}"),
            method = "PUT"
    ),
    @InjectLink(
            resource = PessoaResource.class,
            style = Style.ABSOLUTE,
            rel = "delete",
            bindings = @Binding(name = "id", value = "${instance.id}"),
            method = "DELETE"
    )
})
@XmlJavaTypeAdapter(LinkAdapter.class)
List links;

```

Ao acessar o recurso, ele retornará todos esses links:

![Endpoint de Pessoa com HATEOAS com três links](https://dkrn4sk0rn31v.cloudfront.net/uploads/2020/07/hateoas-header-endpoint-pessoa-com-links.png)

[  ![Java - Banco de dados e JDBC](https://d2knvm16wkt3ia.cloudfront.net/assets/svg-icon/java.svg)   Curso Java - Banco de dados e JDBC Conhecer o curso ](https://www.treinaweb.com.br/curso/java-banco-de-dados-e-jdbc)

## Conclusão

O HATEOAS possui pontos negativos e positivos (que não foram abordados aqui pois este não é o objetivo do artigo), entretanto é um novo padrão de projeto que facilita a compreensão de uma API RESTful. Como a sua implementação não é muito complexa, é algo que deve ser avaliado e sempre que possível implementado nas aplicações.

Por hoje é só, até a próxima :)

- [ #Java ](https://www.treinaweb.com.br/blog/tag/java)
- [ #JAX-RS API ](https://www.treinaweb.com.br/blog/tag/jax-rs-api)
- [ #HATEOAS ](https://www.treinaweb.com.br/blog/tag/hateoas)

Autor

 ![Wladimilson M. Nascimento](//secure.gravatar.com/avatar/f0dd442f156a3eacd2880e9cd0eafbd1?d=mm)

## Wladimilson M. Nascimento

 Instrutor, nerd, cinéfilo e desenvolvedor nas horas vagas. Graduado em Ciências da Computação pela Universidade Metodista de São Paulo. 

 [Todos os artigos](https://www.treinaweb.com.br/blog/autor/wladimilson-m-nascimento)  

## Continue estudando

 Transforme leitura em prática com os cursos e formações da TreinaWeb.

 [Ver cursos](https://www.treinaweb.com.br/cursos)   

  Continue lendo

## Artigos relacionados

- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2020/06/o-que-e-hateoas-400x280.png)  [ Desenvolvimento ](https://www.treinaweb.com.br/blog/categoria/desenvolvimento) 

     6 anos atrás

    ##  [ O que é HATEOAS? ](https://www.treinaweb.com.br/blog/o-que-e-hateoas) 

     HATEOAS é um componente que faz parte da arquitetura REST, cujo objetivo é ajudar os clientes a consumirem uma API sem a necessidade de conhecimento prévio.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2020/09/como-funciona-a-prototipacao-no-desenvolvimento-de-software-400x280.png)  [ Engenharia de Software ](https://www.treinaweb.com.br/blog/categoria/engenharia-de-software) 

     6 anos atrás

    ##  [ Como funciona a prototipação no desenvolvimento de software? ](https://www.treinaweb.com.br/blog/como-funciona-a-prototipacao-no-desenvolvimento-de-software) 

     A prototipação no desenvolvimento de software permite amadurecer ideias, identificar problemas e engajar pessoas no processo de criação de um sistema.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2021/05/arquitetura-software-400x280.jpg)  [ Arquitetura de Software ](https://www.treinaweb.com.br/blog/categoria/arquitetura-de-software) 

     10 anos atrás

    ##  [ Por que a arquitetura do meu software deu errado? ](https://www.treinaweb.com.br/blog/por-que-a-arquitetura-do-meu-software-deu-errado) 

     Alguns desenvolvedores dão somente muita atenção à codificação. Vejamos outros importantes aspectos que precisam ser levados em consideração.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2023/07/DICA-CODIGO-JAVA-1-400x280.jpg)  [ Java ](https://www.treinaweb.com.br/blog/categoria/java) 

     3 anos atrás

    ##  [ Dica de Código: Programação Assíncrona com CompletableFuture no Java ](https://www.treinaweb.com.br/blog/dica-de-codigo-programacao-assincrona-com-completablefuture-no-java) 

     Domine a programação assíncrona com CompletableFuture no Java e impulsione o desempenho de sua aplicação. Leia agora!

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2023/03/Metodologia-bem-organizando-seu-css-400x280.jpg)  [ CSS ](https://www.treinaweb.com.br/blog/categoria/css) 

     4 anos atrás

    ##  [ Metodologia BEM: organizando seu CSS ](https://www.treinaweb.com.br/blog/metodologia-bem-organizando-seu-css) 

     Melhore a qualidade do código CSS em seu projeto web com a Metodologia BEM. Aprenda como aplicá-la e aproveite seus benefícios.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2020/12/CONCEITOS-APRENDIZADO-PROGRAMAÇÃO-400x280.png)  [ Algoritmos ](https://www.treinaweb.com.br/blog/categoria/algoritmos) 

     6 anos atrás

    ##  [ Conceitos usados no aprendizado de programação ](https://www.treinaweb.com.br/blog/conceitos-usados-no-aprendizado-de-programacao) 

     Entenda conceitos utilizados no aprendizado de lógica de programação.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2020/11/C-SHARP-PROPRIEDADES-INIT-RECORD-400x280.png)  [ C# ](https://www.treinaweb.com.br/blog/categoria/csharp) 

     6 anos atrás

    ##  [ C# 9.0 - Programas top-level e Pattern Matching ](https://www.treinaweb.com.br/blog/c-9-0-programas-top-level-e-pattern-matching) 

     Dando continuidade ao nosso estudo do C# 9.0, neste artigo veremos dois novos recursos dele: Programas top-leve e Pattern Matching.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2020/10/big-data-x-data-analytics-x-data-science-quais-as-diferencas-400x280.png)  [ Tecnologia ](https://www.treinaweb.com.br/blog/categoria/tecnologia) 

     6 anos atrás

    ##  [ Big Data x Data Analytics x Data Science: quais as diferenças? ](https://www.treinaweb.com.br/blog/big-data-x-data-analytics-x-data-science-quais-as-diferencas) 

     Confira neste artigo as diferenças entre Big Data, Data Analytics e Data Science, além de conhecer o foco de cada uma delas.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2020/10/data-analytics-o-que-e-e-qual-sua-importancia-400x280.png)  [ Data Science ](https://www.treinaweb.com.br/blog/categoria/data-science) 

     6 anos atrás

    ##  [ Data Analytics: o que é e qual sua importância ](https://www.treinaweb.com.br/blog/data-analytics-o-que-e-e-qual-sua-importancia) 

     Atualmente vivemos na era dos dados. Confira neste artigo o que vem a ser Data Analytics, sua importância e do poder que a informação nos traz.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2020/01/20160410/TABELA-VERDADE-400x280.png)  [ Desenvolvimento ](https://www.treinaweb.com.br/blog/categoria/desenvolvimento) 

     7 anos atrás

    ##  [ Operadores lógicos ](https://www.treinaweb.com.br/blog/operadores-logicos) 

     Operadores lógicos costumam causar dúvidas em quem está aprendendo lógica de programação. Nesse post falaremos sobre operadores lógicos independente de linguagem de programação, veremos suas tabela verdade e exemplos práticos.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2018/07/05201832/capa-erros-vagas-400x280.jpg)  [ Carreira ](https://www.treinaweb.com.br/blog/categoria/carreira) 

     9 anos atrás

    ##  [ Erros que podem estar te impedindo de conseguir a tão sonhada vaga ](https://www.treinaweb.com.br/blog/erros-que-podem-estar-te-impedindo-de-conseguir-a-tao-sonhada-vaga) 

     Que o mercado de TI é super aquecido, já sabemos. Mas você sabe no que precisa se atentar para conseguir a vaga que tanto deseja? Veja nesse artigo se você não está cometendo alguns desses erros.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2023/05/NEST-JS-UPLOAD-ARQUIVOS-400x280.png)  [ Node ](https://www.treinaweb.com.br/blog/categoria/node-js) 

     3 anos atrás

    ##  [ Criando CRUD com Prisma ORM e NestJS ](https://www.treinaweb.com.br/blog/criando-crud-com-prisma-orm-e-nestjs) 

     Neste artigo vamos implementar um CRUD com Prisma ORM e NestJS, abordando as principais operações básicas com o banco de dados.

     Ler artigo

## Um ano de acesso total para você viver de programação.

 Todos os cursos e formações da TreinaWeb numa única assinatura, com professores que atuam no mercado, suporte direto e certificados. Do primeiro `console.log` ao mercado de trabalho.

- **1 ano** de acesso a **todos os cursos**
- Cursos novos **toda semana**
- Suporte **direto com professores**
- Plano de carreira **personalizado**
- **Certificados digitais** inclusos
- **Aplicativos** para Android e iOS, com **acesso offline**

    **Garantia incondicional de satisfação** 

 Teste por 7 dias e, se não fizer sentido para você, devolvemos seu dinheiro.

### Acesso completo a todos os cursos e dezenas de Formações.

 12 meses 

  Economize R$ 840,00  54% OFF 

 de 12x R$ 129,00 por apenas

 12x  R$ 59,00

 sem juros no cartão de crédito ou R$ 599,00 à vista

  Oferta termina em  **13h 17min 01s**

- Acesso imediato e ilimitado durante 1 ano.
- Plano de carreira personalizado.
- Suporte direto com professores.
- E muito mais!

 [Matricule-se agora](https://www.treinaweb.com.br/checkout/pagamento/plano/anual?cupom=TW-SCLIENTE26)

     [                ](https://www.treinaweb.com.br)

 Escola online de programação, tecnologia e IA.

- [  ](https://www.facebook.com/TreinaWeb/)
- [  ](https://www.instagram.com/treinaweb/)
- [  ](https://www.youtube.com/user/TreinaWeb)
- [  ](https://twitter.com/treinaweb)
- [  ](https://www.linkedin.com/company/treinaweb)
- [  ](https://github.com/treinaweb)

## Inscreva-se em nossa newsletter

Receba lançamentos, promoções e novidades.

   Seu nome     Seu WhatsApp     Seu melhor e-mail   Inscrever-se 

## Cursos

- [ Base para Devs ](https://www.treinaweb.com.br/categoria/base-para-devs)
- [ Front-end ](https://www.treinaweb.com.br/categoria/desenvolvimento-front-end)
- [ Back-end ](https://www.treinaweb.com.br/categoria/desenvolvimento-back-end)
- [ Mobile ](https://www.treinaweb.com.br/categoria/desenvolvimento-mobile)
- [ Bancos de Dados ](https://www.treinaweb.com.br/categoria/bancos-de-dados)
- [ Cloud ](https://www.treinaweb.com.br/categoria/cloud-computing)
- [ IA ](https://www.treinaweb.com.br/categoria/ia)
- [ E mais ](https://www.treinaweb.com.br/categoria/e-mais)
- [ Ver todos os cursos ](https://www.treinaweb.com.br/cursos)

## Conteúdo

- [ Formações ](https://www.treinaweb.com.br/formacoes)
- [ Projetos práticos ](https://www.treinaweb.com.br/projetos-praticos)
- [ Direto ao ponto ](https://www.treinaweb.com.br/direto-ao-ponto)
- [ Planos ](https://www.treinaweb.com.br#assinatura)
- [ Depoimentos ](https://www.treinaweb.com.br#depoimentos)
- [ Comunidade ](https://www.treinaweb.com.br#comunidade)
- [ Corpo docente ](https://www.treinaweb.com.br#docente)

## A empresa

- [ Sobre a TreinaWeb ](https://www.treinaweb.com.br#sobre)
- [ Perguntas frequentes ](https://www.treinaweb.com.br#faq)
- [ Vantagens de estudar na TreinaWeb ](https://www.treinaweb.com.br/vantagens-de-estudar-na-treinaweb)
- [ Cursos para empresas ](https://www.treinaweb.com.br/empresas)
- [ Sugira um novo curso ](https://www.treinaweb.com.br/sugerir-curso)
- [ Trabalhe conosco ](https://www.treinaweb.com.br/trabalhe-conosco)
- [ Artigos ](https://www.treinaweb.com.br/blog)
- [ Desenvolvedores e agentes ](https://www.treinaweb.com.br/developers)
- [ Contato ](https://www.treinaweb.com.br/contato)
- [ Política de privacidade ](https://www.treinaweb.com.br/politica-de-privacidade)
- [ Termos de uso ](https://www.treinaweb.com.br/termos-de-uso)

## Baixe nosso aplicativo

 [   Disponível na **App Store**  ](https://apps.apple.com/us/app/treinaweb/id1322729447) [   Disponível no **Google Play**  ](https://play.google.com/store/apps/details?id=br.com.treinaweb.mobile) 

  Av. Paulista, 1765, Conj 71 e 72 · Bela Vista · São Paulo · SP · 01311-200   © 2004 – 2026 TreinaWeb Tecnologia LTDA · CNPJ 06.156.637/0001-58
