/v1/healthPúblicoHealth check
Confirma se o runtime Node/Cloud Run está respondendo.
GET https://cardocs-backend-5qq5b33fha-rj.a.run.app/v1/healthAccept: application/jsonSem body.{
"status": "UP",
"runtime": "node"
}
Tá Revisado..Voltar para o siteAndroid Integration Guide
Guia didático para autenticar com Firebase e consumir o backend Cloud Run com tudo que precisa ser enviado: método, URL, headers, path params, body e respostas esperadas.
Base URL
https://cardocs-backend-5qq5b33fha-rj.a.run.app
Auth
Firebase ID token no header
Endpoints
19 rotas documentadas
Visão geral
O Android faz login com Firebase Auth e envia o ID token no header Authorization.
Não grave direto no Firestore. Todas as mudanças passam pelas rotas `/v1`.
Depois de salvar nota, documento, veículo ou transferência, atualize `/v1/dashboard`.
Setup Android
O exemplo abaixo usa Firebase Auth, OkHttp, Retrofit e Moshi. Você pode trocar Retrofit por Ktor, mas mantenha o mesmo contrato: `Authorization: Bearer`, `Accept: application/json` e `Content-Type: application/json` quando houver body.
// build.gradle.kts (Module: app)
dependencies {
implementation(platform("com.google.firebase:firebase-bom:34.6.0"))
implementation("com.google.firebase:firebase-auth")
implementation("com.squareup.okhttp3:okhttp:4.12.0")
implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")
implementation("com.squareup.retrofit2:retrofit:2.11.0")
implementation("com.squareup.retrofit2:converter-moshi:2.11.0")
implementation("com.squareup.moshi:moshi-kotlin:1.15.1")
}class FirebaseTokenProvider {
suspend fun idToken(forceRefresh: Boolean = false): String {
val user = FirebaseAuth.getInstance().currentUser
?: error("Usuário não autenticado")
return user.getIdToken(forceRefresh).await().token
?: error("Firebase não retornou ID token")
}
}class AuthInterceptor(
private val tokenProvider: FirebaseTokenProvider
) : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val token = runBlocking { tokenProvider.idToken() }
val request = chain.request().newBuilder()
.header("Authorization", "Bearer $token")
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.build()
return chain.proceed(request)
}
}
val okHttp = OkHttpClient.Builder()
.addInterceptor(AuthInterceptor(FirebaseTokenProvider()))
.addInterceptor(HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BASIC
})
.build()interface TaRevisadoApi {
@GET("v1/dashboard")
suspend fun dashboard(): VehicleDashboardDto
@POST("v1/vehicles/plate-lookup")
suspend fun lookupPlate(@Body body: PlateLookupRequest): VehicleCandidateDto
@POST("v1/vehicles")
suspend fun createVehicle(@Body body: VehicleRegistrationRequest): VehicleProfileDto
@POST("v1/invoices/analyze")
suspend fun analyzeInvoice(@Body body: InvoiceDocumentInput): InvoiceScanDraftDto
@POST("v1/invoices")
suspend fun saveInvoice(@Body body: SaveInvoiceRequest): AutomationResultDto
@POST("v1/vehicle-transfers")
suspend fun requestTransfer(@Body body: CreateVehicleTransferRequest): VehicleTransferDto
}
val api = Retrofit.Builder()
.baseUrl("https://cardocs-backend-5qq5b33fha-rj.a.run.app/")
.client(okHttp)
.addConverterFactory(MoshiConverterFactory.create())
.build()
.create(TaRevisadoApi::class.java)Autenticação
Depois do login no Firebase Auth, gere um ID token e envie no header. Se receber `401`, faça refresh forçado do token e repita a chamada uma única vez.
Headers padrão
Authorization: Bearer <firebase-id-token>Accept: application/jsonContent-Type: application/jsonclass TaRevisadoRepository(private val api: TaRevisadoApi) {
suspend fun loadGarage(): Result<VehicleDashboardDto> = runCatching {
api.dashboard()
}
suspend fun registerVehicle(plate: String, mileage: Int): Result<VehicleProfileDto> = runCatching {
val candidate = api.lookupPlate(PlateLookupRequest(plate))
api.createVehicle(
VehicleRegistrationRequest(
plate = candidate.plate,
initialMileage = mileage
)
)
}
}Referência de endpoints
Cada rota mostra exatamente o que enviar: método e URL completa, headers, path params quando existirem, body JSON e resposta representativa. Campos adicionais podem aparecer conforme o histórico do veículo cresce.
Rotas sem autenticação. Use para health check, relatórios públicos e links compartilháveis.
/v1/healthPúblicoConfirma se o runtime Node/Cloud Run está respondendo.
GET https://cardocs-backend-5qq5b33fha-rj.a.run.app/v1/healthAccept: application/jsonSem body.{
"status": "UP",
"runtime": "node"
}/v1/public/reports/{slug}PúblicoBusca o dossiê público de revenda gerado para um veículo.
GET https://cardocs-backend-5qq5b33fha-rj.a.run.app/v1/public/reports/{slug}Accept: application/jsonslug: substitua no path antes de chamar.Sem body.{
"title": "Dossiê Tá Revisado",
"summary": "Histórico consolidado com manutenções...",
"score": 82,
"estimatedValueIncrease": 1250.5,
"publicReportURL": "https://cardocs-backend-5qq5b33fha-rj.a.run.app/r/ABC1D23-2F8A91B0",
"highlights": [],
"checks": [],
"reportSections": []
}/r/{slug}PúblicoRenderiza uma página pública para compartilhar com comprador, anúncio ou vendedor.
GET https://cardocs-backend-5qq5b33fha-rj.a.run.app/r/{slug}Accept: text/htmlslug: substitua no path antes de chamar.Sem body.HTTP 200
Content-Type: text/html; charset=utf-8Rotas que ligam o usuário Firebase à conta Tá Revisado e mantêm o dispositivo Android sincronizado.
/v1/meBearer Firebase ID tokenSincroniza o usuário autenticado no Firebase Auth com o backend Tá Revisado
POST https://cardocs-backend-5qq5b33fha-rj.a.run.app/v1/meAuthorization: Bearer <firebase-id-token>
Accept: application/jsonSem body.{
"id": "firebase-uid",
"email": "cliente@email.com",
"displayName": "Cliente Tá Revisado",
"photoURL": null,
"emailVerified": true,
"signInProvider": "password",
"providerIds": ["password"]
}/v1/meBearer Firebase ID tokenRemove dados do usuário no Firestore/Storage antes de excluir a conta no Firebase Auth.
DELETE https://cardocs-backend-5qq5b33fha-rj.a.run.app/v1/meAuthorization: Bearer <firebase-id-token>
Accept: application/jsonSem body.HTTP 204 No Content/v1/device-tokensBearer Firebase ID tokenRegistra o token FCM do aparelho para alertas de transferência de veículo.
POST https://cardocs-backend-5qq5b33fha-rj.a.run.app/v1/device-tokensAuthorization: Bearer <firebase-id-token>
Content-Type: application/json
Accept: application/json{
"token": "fcm-token-do-aparelho",
"platform": "ios"
}HTTP 204 No Content/v1/device-tokens/removeBearer Firebase ID tokenRemove o token FCM no logout, troca de conta ou revogação de permissão.
POST https://cardocs-backend-5qq5b33fha-rj.a.run.app/v1/device-tokens/removeAuthorization: Bearer <firebase-id-token>
Content-Type: application/json
Accept: application/json{
"token": "fcm-token-do-aparelho"
}HTTP 204 No ContentFluxo principal para carregar dashboard, consultar placa real e cadastrar veículo na garagem.
/v1/dashboardBearer Firebase ID tokenRetorna garagem, veículo selecionado, documentos, histórico, dossiê e transferências pendentes.
GET https://cardocs-backend-5qq5b33fha-rj.a.run.app/v1/dashboardAuthorization: Bearer <firebase-id-token>
Accept: application/jsonSem body.{
"id": "dashboard-id",
"garages": [],
"selectedGarageID": "00000000-0000-5000-8000-000000000000",
"detectedVehicle": {
"id": "00000000-0000-5000-8000-000000000000",
"kind": "car",
"plate": "",
"brand": "",
"model": "",
"year": "",
"color": "",
"image": null,
"fipe": null,
"details": null
},
"incomingVehicleTransfers": [],
"outgoingVehicleTransfers": []
}/v1/vehicles/plate-lookupBearer Firebase ID tokenBusca dados reais do veículo por placa antes de permitir o cadastro.
POST https://cardocs-backend-5qq5b33fha-rj.a.run.app/v1/vehicles/plate-lookupAuthorization: Bearer <firebase-id-token>
Content-Type: application/json
Accept: application/json{
"plate": "ABC1D23"
}{
"id": "candidate-id",
"kind": "car",
"plate": "ABC1D23",
"brand": "Toyota",
"model": "Corolla",
"year": "2022",
"color": "Prata",
"image": null,
"fipe": null,
"details": null
}/v1/vehiclesBearer Firebase ID tokenCadastra o veículo depois de revalidar a placa no backend.
POST https://cardocs-backend-5qq5b33fha-rj.a.run.app/v1/vehiclesAuthorization: Bearer <firebase-id-token>
Content-Type: application/json
Accept: application/json{
"plate": "ABC1D23",
"initialMileage": 42000
}{
"id": "vehicle-id",
"kind": "car",
"plate": "ABC1D23",
"maskedPlate": "ABC1D2*",
"brand": "Toyota",
"model": "Corolla",
"year": "2022",
"color": "Prata",
"mileage": 42000,
"nextServiceTitle": "Primeira organizacao",
"nextServiceDistance": "Pronto para importar historico",
"statusTags": ["Placa Verificada"]
}/v1/vehicles/imageBearer Firebase ID tokenConsulta imagem do veículo por marca, modelo e ano.
POST https://cardocs-backend-5qq5b33fha-rj.a.run.app/v1/vehicles/imageAuthorization: Bearer <firebase-id-token>
Content-Type: application/json
Accept: application/json{
"brand": "Toyota",
"model": "Corolla",
"year": "2022"
}{
"url": "https://...",
"thumbnailUrl": "https://...",
"mime": "image/jpeg",
"width": 1024,
"height": 768,
"accentColor": "#8A8889",
"source": "carsxe"
}Rotas para análise de documento, persistência no histórico e cofre digital do veículo.
/v1/invoices/analyzeBearer Firebase ID tokenExtrai dados estruturados a partir de OCR ou arquivo enviado em base64.
POST https://cardocs-backend-5qq5b33fha-rj.a.run.app/v1/invoices/analyzeAuthorization: Bearer <firebase-id-token>
Content-Type: application/json
Accept: application/json{
"source": "cameraScan",
"displayName": "nota-oficina.pdf",
"ocrText": "Texto extraído no Android...",
"pageCount": 1,
"document": {
"mimeType": "application/pdf",
"base64Data": "JVBERi0xLjQ..."
}
}{
"id": "draft-id",
"source": "cameraScan",
"supplierName": "Oficina Central",
"serviceTitle": "Troca de óleo",
"category": "Manutenção",
"date": "2026-05-12",
"amount": 389.9,
"mileage": 42310,
"confidence": 91,
"lineItems": [],
"extractedFields": [],
"healthImpacts": []
}/v1/invoicesBearer Firebase ID tokenTransforma um draft analisado em registro de manutenção e documento no cofre.
POST https://cardocs-backend-5qq5b33fha-rj.a.run.app/v1/invoicesAuthorization: Bearer <firebase-id-token>
Content-Type: application/json
Accept: application/json{
"vehicleID": "vehicle-id",
"draft": {
"id": "draft-id",
"source": "cameraScan",
"supplierName": "Oficina Central",
"serviceTitle": "Troca de óleo",
"category": "Manutenção",
"date": "2026-05-12",
"amount": 389.9,
"mileage": 42310,
"confidence": 91,
"lineItems": [],
"extractedFields": [],
"healthImpacts": []
},
"sourceDocument": null
}{
"title": "Troca de óleo registrada",
"message": "Histórico atualizado.",
"investmentDelta": {
"total": 389.9,
"maintenance": 389.9,
"documentsAndTaxes": 0
},
"record": {},
"document": {}
}/v1/documentsBearer Firebase ID tokenSalva documento do veículo, como CRLV, IPVA, recibos e comprovantes.
POST https://cardocs-backend-5qq5b33fha-rj.a.run.app/v1/documentsAuthorization: Bearer <firebase-id-token>
Content-Type: application/json
Accept: application/json{
"vehicleID": "vehicle-id",
"title": "CRLV 2026",
"documentType": "CRLV",
"date": "2026",
"notes": "Documento atualizado",
"sourceDocument": {
"source": "fileImport",
"displayName": "crlv.pdf",
"pageCount": 1,
"document": {
"mimeType": "application/pdf",
"base64Data": "JVBERi0xLjQ..."
}
}
}{
"id": "document-id",
"title": "CRLV 2026",
"status": "Anexado",
"kind": "vehicleDocument",
"documentType": "CRLV",
"attachment": {
"storagePath": "users/.../crlv.pdf",
"downloadURL": "https://...",
"mimeType": "application/pdf",
"fileName": "crlv.pdf",
"sizeBytes": 120000,
"pageCount": 1,
"source": "fileImport"
}
}/v1/documents/updateBearer Firebase ID tokenAtualiza metadados editáveis de um documento salvo.
POST https://cardocs-backend-5qq5b33fha-rj.a.run.app/v1/documents/updateAuthorization: Bearer <firebase-id-token>
Content-Type: application/json
Accept: application/json{
"vehicleID": "vehicle-id",
"documentID": "document-id",
"title": "CRLV atualizado",
"date": "2026",
"documentType": "CRLV",
"notes": "Emitido no app oficial"
}{ ...vaultDocument }/v1/maintenance-records/updateBearer Firebase ID tokenAtualiza título, subtítulo, data, valor e resumo de uma manutenção.
POST https://cardocs-backend-5qq5b33fha-rj.a.run.app/v1/maintenance-records/updateAuthorization: Bearer <firebase-id-token>
Content-Type: application/json
Accept: application/json{
"vehicleID": "vehicle-id",
"recordID": "record-id",
"title": "Revisão 40 mil km",
"subtitle": "Óleo, filtros e inspeção",
"date": "2026-05-12",
"amount": 720,
"supplierName": "Oficina Central",
"serviceTitle": "Revisão completa",
"purchaseSummary": "Óleo, filtros e mão de obra"
}{ ...maintenanceRecord }Rotas para gerar relatório de revenda e mover um veículo para outro usuário Tá Revisado
/v1/resale-dossiersBearer Firebase ID tokenGera ou atualiza o relatório público do veículo.
POST https://cardocs-backend-5qq5b33fha-rj.a.run.app/v1/resale-dossiersAuthorization: Bearer <firebase-id-token>
Content-Type: application/json
Accept: application/json{
"vehicleID": "vehicle-id"
}{
"title": "Dossiê Tá Revisado",
"summary": "Histórico consolidado...",
"score": 82,
"estimatedValueIncrease": 1250.5,
"publicReportURL": "https://cardocs-backend-5qq5b33fha-rj.a.run.app/r/ABC1D23-2F8A91B0",
"highlights": [],
"checks": [],
"reportSections": []
}/v1/vehicle-transfersBearer Firebase ID tokenEnvia o veículo para o e-mail de outro usuário. O novo dono precisa aceitar no app.
POST https://cardocs-backend-5qq5b33fha-rj.a.run.app/v1/vehicle-transfersAuthorization: Bearer <firebase-id-token>
Content-Type: application/json
Accept: application/json{
"vehicleID": "vehicle-id",
"recipientEmail": "comprador@email.com"
}{
"id": "transfer-id",
"vehicleID": "vehicle-id",
"vehiclePlate": "ABC1D23",
"vehicleTitle": "Toyota Corolla",
"fromOwnerID": "uid-vendedor",
"fromOwnerEmail": "vendedor@email.com",
"toOwnerID": "uid-comprador",
"toOwnerEmail": "comprador@email.com",
"status": "pending"
}/v1/vehicle-transfers/respondBearer Firebase ID tokenO destinatário aceita ou recusa uma transferência pendente.
POST https://cardocs-backend-5qq5b33fha-rj.a.run.app/v1/vehicle-transfers/respondAuthorization: Bearer <firebase-id-token>
Content-Type: application/json
Accept: application/json{
"transferID": "transfer-id",
"action": "accept"
}{
"transfer": {
"id": "transfer-id",
"status": "accepted"
},
"dashboard": {
"garages": [],
"incomingVehicleTransfers": [],
"outgoingVehicleTransfers": []
}
}Erros e retries
{
"error": "validation_error",
"message": "Requisicao invalida.",
"details": [
{
"path": "vehicleID",
"message": "Too small: expected string to have >=1 characters"
}
]
}fun File.toBase64Payload(mimeType: String): InvoiceDocumentContent {
val bytes = readBytes()
require(bytes.size <= 20_000_000) { "Documento maior que o limite da API" }
return InvoiceDocumentContent(
mimeType = mimeType,
base64Data = Base64.encodeToString(bytes, Base64.NO_WRAP)
)
}Checklist de produção