Como funciona
- 1 · vocêPublica o feedUma URL HTTPS com todas as vagas abertas dos clientes que divulgam na Remotar.
- 2 · RemotarLê a URLA cada poucas horas, sem nenhuma ação sua.
- 3 · RemotarCura e publicaVaga nova entra na curadoria. Vaga que sumiu do feed é encerrada.
- 4 · candidatoCandidata-se no seu ATSO botão leva ao
applyUrlda vaga. A candidatura acontece no seu sistema.
O feed é sempre uma fotografia completa, não uma lista de alterações. Não é preciso marcar vaga como nova, alterada ou removida: basta o feed refletir o estado atual.
Requisitos da URL
- HTTPS, respondendo
GETcom status200eContent-Type: application/xml. - Codificação UTF-8.
- URL estável. Se precisar de chave de acesso, coloque-a na própria URL (
?token=…). Não suportamos cabeçalhos de autenticação. - Resposta completa em menos de 60 segundos. Recomendamos manter o arquivo abaixo de 20 MB.
Estrutura
<?xml version="1.0" encoding="UTF-8"?> <remotarFeed version="1.0"> <generatedAt>2026-09-21T09:00:00-03:00</generatedAt> <jobs> <job> <id>vaga-10482</id> <title>Pessoa Desenvolvedora Back-end Python Sênior</title> <description><![CDATA[<p>Descrição em HTML…</p>]]></description> <applyUrl>https://vagas.seu-ats.com.br/acme/vaga-10482</applyUrl> <workplace>remote</workplace> <company> <id>acme</id> <name>Acme Pagamentos</name> </company> </job> </jobs> </remotarFeed>
versioné obrigatório e deve ser1.0nesta versão do formato.generatedAté o momento em que o arquivo foi gerado (ISO 8601 com fuso).- Dentro de
<job>e de<company>, os elementos podem vir em qualquer ordem. - Use
<![CDATA[ … ]]>em textos com HTML ou com os caracteres<e&.
Campos da vaga
Obrigatórios
| Campo | Formato | Regra |
|---|---|---|
id | Letras, números e . _ : -, até 100 caracteres | Identificador estável e único da vaga no seu ATS. Veja Identificadores. |
title | Texto, até 255 caracteres | Título da vaga, sem código interno nem nome da empresa. |
description | HTML, até 50.000 caracteres | Descrição completa: responsabilidades, requisitos e o que mais houver. |
applyUrl | URL https:// | Página de candidatura desta vaga no seu ATS. |
workplace | remote · hybrid · onsite | Modelo de trabalho. Veja Quais vagas entram. |
company | Bloco | Empresa que contrata. Veja Campos da empresa. |
location | <city> e <state> | Obrigatório em vaga híbrida. Cidade e UF de 2 letras (ex.: SP) do escritório. |
Opcionais
Os opcionais melhoram a vaga na Remotar: aparecem como filtro, selo ou informação destacada. Mande sempre que tiver o dado.
| Campo | Formato | Uso |
|---|---|---|
publishedAt | Data e hora ISO 8601 | Data em que a vaga foi aberta. |
contractType | clt · pj · internship · temporary · freelancer · other | Tipo de contratação. |
seniority | internship · junior · mid · senior · specialist · lead | Nível da vaga. |
salary | min · max · currency · period | Faixa salarial. Veja Salário. |
category | Texto, até 255 caracteres | Área da vaga no seu ATS (ex.: "Tecnologia"). |
pcd | true · false | true quando a vaga é exclusiva ou afirmativa para pessoas com deficiência. |
benefits | Lista de <benefit>, até 50 | Benefícios oferecidos, um por item. |
Campos da empresa
| Campo | Obrigatório | Regra |
|---|---|---|
id | sim | Identificador estável do seu cliente. Todas as vagas da mesma empresa trazem o mesmo id. |
name | sim | Nome público da empresa, até 255 caracteres. Não use "Confidencial": vaga sem empresa identificada não é publicada. |
website | não | Site institucional. Ajuda a identificar a empresa na Remotar. |
logoUrl | não | Logo em PNG, JPG ou SVG. |
description | não | Apresentação curta da empresa, em texto ou HTML. |
Quais vagas entram
A Remotar publica apenas vagas remotas e híbridas.
workplace | Resultado | Observação |
|---|---|---|
remote | entra | Segue para a curadoria. |
hybrid com location | entra | Segue para a curadoria. |
hybrid sem location | descartada | Sem cidade e UF, a pessoa não sabe onde fica o escritório. |
onsite | ignorada | Pode vir no feed. Assim você não precisa filtrar. |
Toda vaga passa pela curadoria da Remotar antes de aparecer no site. Na primeira vaga de uma empresa nova, também confirmamos a empresa. Por isso, a publicação não é imediata, e uma vaga pode não ser publicada se não seguir as políticas da Remotar.
Identificadores
O id da vaga e o id da empresa são o que liga o seu feed ao que está publicado na Remotar.
- Nunca mude o
idde uma vaga existente. Para nós, umidnovo é uma vaga nova, e o antigo é uma vaga encerrada. - Nunca reaproveite um
idpara outra vaga, mesmo depois de a primeira ser encerrada. - Use o identificador interno do seu banco, não o título nem a URL.
- O
idda empresa é o mesmo em todas as vagas dela e em todas as leituras. Se o cliente mudar de nome, oidcontinua o mesmo.
Ciclo de vida da vaga
| Situação | No feed | Na Remotar |
|---|---|---|
| Vaga aberta | Presente | Publica, depois da curadoria. |
| Vaga alterada | Presente, com os dados novos | Atualiza. |
| Vaga fechada ou pausada | Ausente | Encerra a vaga. |
| Vaga reaberta | Volta, com o mesmo id | Reativa a vaga. |
| Nenhuma vaga aberta | <jobs/> vazio, num feed válido | Encerra todas as vagas do feed. |
| Feed fora do ar ou inválido | Erro HTTP, timeout ou XML inválido | Nada muda. Mantém o último estado e tenta de novo na próxima leitura. |
Um feed com erro nunca derruba as vagas publicadas. Só um feed válido e sem aquela vaga a encerra.
Descrição e salário
Descrição
- Envie HTML simples:
p,br,ul,ol,li,strong,em,h2–h4ea. Scripts, estilos, iframes, imagens e atributos de formatação são removidos. - Não inclua o link de candidatura na descrição: ele vem em
applyUrl. - Descrições muito curtas prejudicam a curadoria e podem impedir a publicação.
Salário
<salary> <min>12000</min> <max>16000</max> <currency>BRL</currency> <period>month</period> </salary>
- Valores inteiros, sem separador de milhar nem centavos.
maxé obrigatório dentro desalary. Para salário fixo, mande sómax.currency:BRL,USDouEUR.period:hour,monthouyear.- Se a vaga não divulga salário, omita o bloco inteiro. Não mande
0.
Link de candidatura e rastreamento
Ao enviar a pessoa para o applyUrl, a Remotar acrescenta utm_source=remotar à URL, a menos que ela já traga um utm_source. Assim você mede as candidaturas vindas da Remotar. Garanta que o seu ATS aceite parâmetros extras na URL de candidatura.
Validando o feed
O XSD confere estrutura e formatos. Com xmllint:
xmllint --noout --schema remotar-feed-v1.xsd seu-feed.xml
Ou em Python, com lxml:
from lxml import etree
schema = etree.XMLSchema(etree.parse("remotar-feed-v1.xsd"))
feed = etree.parse("seu-feed.xml")
schema.assertValid(feed)O XSD não expressa duas regras, que conferimos na leitura: vaga hybrid precisa de location, e o id de cada empresa precisa ser estável entre leituras.
Elementos fora do esquema tornam o feed inválido. Se você precisa mandar um dado que o formato não prevê, fale com a gente: o formato cresce por versão.
Checklist antes de enviar a URL
- O feed valida contra
remotar-feed-v1.xsd. - A URL responde por HTTPS em menos de 60 segundos.
- O feed contém todas as vagas abertas, não só as recentes.
- Os
ids de vaga e de empresa vêm do seu banco e não mudam. - Toda vaga híbrida tem cidade e UF.
- O
applyUrlabre a candidatura da vaga certa, sem exigir login prévio. - O
applyUrlcontinua funcionando com?utm_source=remotarno final.
Próximo passo
Com o feed validado, envie à Remotar a URL do feed, o nome do seu ATS com um contato técnico e, se houver, a lista dos clientes que já têm vagas no feed. Fazemos uma leitura de teste, mostramos o resultado (vagas aceitas, descartadas e o motivo de cada descarte) e só então ativamos a integração.
Versionamento
- Mudanças compatíveis, como um campo opcional novo, sobem a versão menor:
1.1,1.2. Um feed1.0continua válido. - Mudanças incompatíveis geram uma versão
2.0, com novo XSD e prazo de transição combinado com cada parceiro.
XSD e exemplo
Os dois arquivos oficiais da versão 1.0: remotar-feed-v1.xsd e exemplo-v1.xml. O exemplo traz uma vaga remota completa, uma híbrida e uma só com os campos obrigatórios, e valida contra o XSD.
Exemplo de feed exemplo-v1.xml
<?xml version="1.0" encoding="UTF-8"?> <remotarFeed version="1.0"> <generatedAt>2026-09-21T09:00:00-03:00</generatedAt> <jobs> <!-- Vaga remota, com todos os campos opcionais preenchidos --> <job> <id>vaga-10482</id> <title>Pessoa Desenvolvedora Back-end Python Sênior</title> <description><![CDATA[ <p>Buscamos uma pessoa desenvolvedora para evoluir nossa plataforma de pagamentos.</p> <h3>Responsabilidades</h3> <ul> <li>Projetar e manter APIs em Python (FastAPI)</li> <li>Participar das decisões de arquitetura</li> </ul> <h3>Requisitos</h3> <ul> <li>Experiência sólida com Python e PostgreSQL</li> <li>Vivência com filas e mensageria</li> </ul> ]]></description> <applyUrl>https://vagas.exemplo-ats.com.br/acme/vaga-10482</applyUrl> <workplace>remote</workplace> <publishedAt>2026-09-18T14:30:00-03:00</publishedAt> <contractType>pj</contractType> <seniority>senior</seniority> <salary> <min>12000</min> <max>16000</max> <currency>BRL</currency> <period>month</period> </salary> <category>Tecnologia</category> <pcd>false</pcd> <benefits> <benefit>Auxílio home office</benefit> <benefit>Plano de saúde</benefit> </benefits> <company> <id>acme</id> <name>Acme Pagamentos</name> <website>https://acme.com.br</website> <logoUrl>https://acme.com.br/logo.png</logoUrl> <description>Fintech que simplifica pagamentos para pequenos negócios.</description> </company> </job> <!-- Vaga híbrida: location é obrigatório --> <job> <id>vaga-10517</id> <title>Analista de Dados Pleno</title> <description><![CDATA[<p>Apoie o time comercial com análises e dashboards.</p>]]></description> <applyUrl>https://vagas.exemplo-ats.com.br/beta/vaga-10517</applyUrl> <workplace>hybrid</workplace> <location> <city>Belo Horizonte</city> <state>MG</state> </location> <contractType>clt</contractType> <company> <id>beta-logistica</id> <name>Beta Logística</name> </company> </job> <!-- Vaga só com os campos obrigatórios --> <job> <id>vaga-10533</id> <title>Designer de Produto</title> <description><![CDATA[<p>Desenhe a experiência do nosso app.</p>]]></description> <applyUrl>https://vagas.exemplo-ats.com.br/acme/vaga-10533</applyUrl> <workplace>remote</workplace> <company> <id>acme</id> <name>Acme Pagamentos</name> </company> </job> </jobs> </remotarFeed>
Esquema remotar-feed-v1.xsd
<?xml version="1.0" encoding="UTF-8"?> <!-- Feed de vagas Remotar — versão 1.0 Esquema do XML que um ATS publica para enviar vagas à Remotar. Guia completo: README.md, na mesma pasta. Os filhos de <job> e de <company> podem vir em qualquer ordem. Elementos fora deste esquema tornam o feed inválido: se precisar de um campo novo, fale com a Remotar. --> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> <xs:element name="remotarFeed"> <xs:complexType> <xs:sequence> <xs:element name="generatedAt" type="xs:dateTime"/> <xs:element name="jobs"> <xs:complexType> <xs:sequence> <xs:element name="job" type="Job" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:unique name="jobIdUnico"> <xs:selector xpath="job"/> <xs:field xpath="id"/> </xs:unique> </xs:element> </xs:sequence> <xs:attribute name="version" use="required"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:pattern value="1\.[0-9]+"/> </xs:restriction> </xs:simpleType> </xs:attribute> </xs:complexType> </xs:element> <xs:complexType name="Job"> <xs:all> <!-- Obrigatórios --> <xs:element name="id" type="Identificador"/> <xs:element name="title" type="TextoCurto"/> <xs:element name="description" type="TextoLongo"/> <xs:element name="applyUrl" type="UrlHttps"/> <xs:element name="workplace" type="Workplace"/> <xs:element name="company" type="Company"/> <!-- Obrigatório quando workplace = hybrid ou onsite --> <xs:element name="location" type="Location" minOccurs="0"/> <!-- Opcionais --> <xs:element name="publishedAt" type="xs:dateTime" minOccurs="0"/> <xs:element name="contractType" type="ContractType" minOccurs="0"/> <xs:element name="seniority" type="Seniority" minOccurs="0"/> <xs:element name="salary" type="Salary" minOccurs="0"/> <xs:element name="category" type="TextoCurto" minOccurs="0"/> <xs:element name="pcd" type="xs:boolean" minOccurs="0"/> <xs:element name="benefits" type="Benefits" minOccurs="0"/> </xs:all> </xs:complexType> <xs:complexType name="Company"> <xs:all> <xs:element name="id" type="Identificador"/> <xs:element name="name" type="TextoCurto"/> <xs:element name="website" type="UrlHttp" minOccurs="0"/> <xs:element name="logoUrl" type="UrlHttp" minOccurs="0"/> <xs:element name="description" type="TextoLongo" minOccurs="0"/> </xs:all> </xs:complexType> <xs:complexType name="Location"> <xs:all> <xs:element name="city" type="TextoCurto"/> <xs:element name="state" type="UF"/> </xs:all> </xs:complexType> <xs:complexType name="Salary"> <xs:all> <xs:element name="min" type="xs:nonNegativeInteger" minOccurs="0"/> <xs:element name="max" type="xs:positiveInteger"/> <xs:element name="currency" type="Currency"/> <xs:element name="period" type="SalaryPeriod"/> </xs:all> </xs:complexType> <xs:complexType name="Benefits"> <xs:sequence> <xs:element name="benefit" type="TextoCurto" maxOccurs="50"/> </xs:sequence> </xs:complexType> <!-- Tipos simples --> <xs:simpleType name="Identificador"> <xs:restriction base="xs:string"> <xs:minLength value="1"/> <xs:maxLength value="100"/> <xs:pattern value="[A-Za-z0-9._:\-]+"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="TextoCurto"> <xs:restriction base="xs:string"> <xs:minLength value="1"/> <xs:maxLength value="255"/> <xs:pattern value=".*\S.*"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="TextoLongo"> <xs:restriction base="xs:string"> <xs:minLength value="1"/> <xs:maxLength value="50000"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="UrlHttps"> <xs:restriction base="xs:anyURI"> <xs:pattern value="https://.+"/> <xs:maxLength value="2000"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="UrlHttp"> <xs:restriction base="xs:anyURI"> <xs:pattern value="https?://.+"/> <xs:maxLength value="2000"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="Workplace"> <xs:restriction base="xs:string"> <xs:enumeration value="remote"/> <xs:enumeration value="hybrid"/> <xs:enumeration value="onsite"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="UF"> <xs:restriction base="xs:string"> <xs:enumeration value="AC"/><xs:enumeration value="AL"/><xs:enumeration value="AP"/> <xs:enumeration value="AM"/><xs:enumeration value="BA"/><xs:enumeration value="CE"/> <xs:enumeration value="DF"/><xs:enumeration value="ES"/><xs:enumeration value="GO"/> <xs:enumeration value="MA"/><xs:enumeration value="MT"/><xs:enumeration value="MS"/> <xs:enumeration value="MG"/><xs:enumeration value="PA"/><xs:enumeration value="PB"/> <xs:enumeration value="PR"/><xs:enumeration value="PE"/><xs:enumeration value="PI"/> <xs:enumeration value="RJ"/><xs:enumeration value="RN"/><xs:enumeration value="RS"/> <xs:enumeration value="RO"/><xs:enumeration value="RR"/><xs:enumeration value="SC"/> <xs:enumeration value="SP"/><xs:enumeration value="SE"/><xs:enumeration value="TO"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="ContractType"> <xs:restriction base="xs:string"> <xs:enumeration value="clt"/> <xs:enumeration value="pj"/> <xs:enumeration value="internship"/> <xs:enumeration value="temporary"/> <xs:enumeration value="freelancer"/> <xs:enumeration value="other"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="Seniority"> <xs:restriction base="xs:string"> <xs:enumeration value="internship"/> <xs:enumeration value="junior"/> <xs:enumeration value="mid"/> <xs:enumeration value="senior"/> <xs:enumeration value="specialist"/> <xs:enumeration value="lead"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="Currency"> <xs:restriction base="xs:string"> <xs:enumeration value="BRL"/> <xs:enumeration value="USD"/> <xs:enumeration value="EUR"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="SalaryPeriod"> <xs:restriction base="xs:string"> <xs:enumeration value="hour"/> <xs:enumeration value="month"/> <xs:enumeration value="year"/> </xs:restriction> </xs:simpleType> </xs:schema>