Reference index
API Reference
Real endpoints, straight from the OpenAPI contracts in the API repository: nothing here is made up. BFF cookie session with Keycloak SSO, the user profile and the countries microservice.
Overview
The API's cross-cutting contract: servers, keys and languages.
Every call carries X-PUBLIC-KEY, the public key identifying the platform. Authenticated routes use the session cookie the login returns, and the ones that change something echo the XSRF-TOKEN cookie in the X-XSRF-TOKEN header; the login also talks to Keycloak, and the jwt block may come back null without invalidating the session. Accept-Language (pt-BR, en, es, gn) translates names and messages.
Servers
https://echosistema.live # production https://echosistema.dev # QA / sandbox
Authenticate user
POST/api/v1/authBasic (email:password)
Authenticates with HTTP Basic credentials. On success the session is delivered as an HttpOnly cookie (`echosistema_bff_session`) alongside the readable CSRF cookie (`XSRF-TOKEN`): the response's `token` field is always an empty string and carries no credential. It also attempts an SSO JWT from Keycloak, returned in `jwt` — a `null` there does not mean the login failed. Pass `?with_projects=true` to include the accessible projects.
Headers
X-PUBLIC-KEYstring (uuid)requiredPublic key identifying the platform.
Accept-LanguagestringResponse language: pt-BR, en, es or gn.
Query
with_projectsbooleanWhen true, includes data.user.accessible_projects in the response.
Body
devicestringrequiredName of the device labelling the session in the account's list of connected devices.
flash_tokenbooleanWhen true, returns a 60-second, single-use, IP-bound flash token for cross-frontend handoff via POST /api/v1/auth/flash-token.
Responses
- 200
Authenticated; the cookie's session is always valid, the jwt may be null.
- 401
Invalid credentials or missing/wrong public key.
- 422
Validation error in fields or parameters.
- 500
Internal error.
Request
curl -X POST https://echosistema.live/api/v1/auth \
-u "sample.user@domain.com:secret123" \
-H "X-PUBLIC-KEY: 33333333-3333-3333-3333-333333333333" \
-H "Accept-Language: pt-BR" \
-H "Content-Type: application/json" \
-c cookies.txt \
-d '{ "device": "web-browser" }'Response 200
{
"message": "User authenticated successfully!",
"token": "",
"data": {
"user": {
"uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"echo_uuid": "e1c1h1o1a1b2c3d4e5f6789012345678901234",
"name": "Sample User",
"email": "sample.user@domain.com",
"avatar": { "url": "https://example.com/avatar.png", "usage": "avatar" },
"language": "en",
"currency": "USD",
"roles": [
{
"id": 1,
"platform": {
"uuid": "22222222-2222-2222-2222-222222222222",
"name": "Sample Platform",
"public_key": "33333333-3333-3333-3333-333333333333"
},
"name": "guest",
"localized_name": "Guest",
"permissions": [ { "subject": "complaint", "action": "store" } ]
}
],
"company_roles": [
{
"id": 3,
"platform": {
"uuid": "22222222-2222-2222-2222-222222222222",
"name": "Sample Platform",
"public_key": "33333333-3333-3333-3333-333333333333"
},
"company": {
"id": "64a1b2c3d4e5f6a7b8c9d0e1",
"uuid": "44444444-4444-4444-4444-444444444444",
"name": "Sample Company"
},
"name": "manager",
"localized_name": "Manager",
"permissions": [
{ "subject": "company", "action": "view" },
{ "subject": "company", "action": "update" }
]
}
],
"is_backoffice": false,
"is_service_provider": false
}
},
"jwt": {
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.example",
"refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.refresh",
"id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.idtoken",
"token_type": "Bearer",
"expires_in": 300,
"refresh_expires_in": 1800,
"scope": "openid profile email",
"issuer": "https://sso.echosistema.live/realms/echosistema",
"subject": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"provider": { "driver": "keycloak", "name": "Keycloak Default", "kind": "oidc" }
},
"visitor_ip": "203.0.113.42"
}Try endpoint
Register user
POST/api/v1/auth/registerPublic
Creates the user on the X-PUBLIC-KEY's platform and projects the identity into Keycloak. On realestate platforms the agent, professional and customer flags decide the role, in that order of priority; with no flag the user comes in as guest, and it is one role per platform. The session arrives as a cookie and the jwt block comes back as in the login.
Headers
X-PUBLIC-KEYstring (uuid)requiredPublic key identifying the platform.
Accept-LanguagestringResponse language: pt-BR, en, es or gn.
Query
with_projectsbooleanWhen true, includes data.user.accessible_projects in the response.
Body
namestringrequiredUser full name.
emailstring (email)requiredEmail, unique per platform.
passwordstring (min 8)requiredPassword, 8 characters minimum.
password_confirmationstringrequiredConfirmation, must match the password.
devicestringrequiredName of the device labelling the session in the account's list of connected devices.
flash_tokenbooleanWhen true, returns a 60-second, single-use, IP-bound flash token for cross-frontend handoff via POST /api/v1/auth/flash-token.
agent0 | 1Real-estate agent role on realestate platforms (1 = yes); priority agent, then professional, then customer.
professional0 | 1Professional role on realestate platforms (1 = yes).
customer0 | 1Customer role on realestate platforms (1 = yes).
intend_agency0 | 1Flags the intent to create or join a real-estate agency; stored in the user's raw metadata.
collaborator0 | 1Creates as collaborator (1 = yes); requires gender, birth date, nationalities, address and contacts.
languagestringUser preferred language (IETF locale).
currencystringUser preferred currency.
Responses
- 200
Registered; recently_created true and token at the root.
- 422
Validation error in fields or parameters.
- 500
Internal error.
Request
curl -X POST https://echosistema.live/api/v1/auth/register \
-H "X-PUBLIC-KEY: aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" \
-H "Content-Type: application/json" \
-d '{
"name": "User Example",
"email": "user@example.com",
"password": "secret123",
"password_confirmation": "secret123",
"device": "web"
}'Response 200
{
"message": "User Example registered successfully.",
"recently_created": true,
"token": "0000|a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0",
"data": {
"user": {
"uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"echo_uuid": "e1c1h1o1a1b2c3d4e5f6789012345678901234",
"name": "User Example",
"email": "user@example.com",
"avatar": null,
"language": "en",
"currency": "USD",
"roles": [
{
"id": 1,
"platform": {
"uuid": "22222222-2222-2222-2222-222222222222",
"name": "Example Platform",
"public_key": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
},
"name": "guest",
"localized_name": "Guest",
"permissions": [ { "subject": "complaint", "action": "store" } ]
}
],
"is_backoffice": false,
"is_service_provider": false
}
},
"jwt": {
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.example",
"refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.refresh",
"id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.idtoken",
"token_type": "Bearer",
"expires_in": 300,
"refresh_expires_in": 1800,
"scope": "openid profile email",
"issuer": "https://sso.echosistema.live/realms/echosistema",
"subject": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"provider": { "driver": "keycloak", "name": "Keycloak Default", "kind": "oidc" }
},
"visitor_ip": "203.0.113.42"
}Try endpoint
Log out
POST/api/v1/auth/logoutSession cookie
Revokes the BFF session (destroying the Redis mapping the cookie points at) and tells the browser to drop both cookies, the session one and the CSRF one. It attempts to end the Keycloak session on a best-effort basis, using the cached refresh_token. No request body; the `X-XSRF-TOKEN` header is required. The response is 200 even when Keycloak fails.
Headers
CookiestringrequiredThe BFF session cookie `echosistema_bff_session`, set by the login. The browser attaches it on its own; with curl, use `-b`.
X-XSRF-TOKENstringrequiredThe `XSRF-TOKEN` cookie's value, echoed back as a header. Required on every request that changes something, whenever a session cookie is present.
Responses
- 200
Token revoked, best-effort; always 200.
- 401
No valid session: cookie missing, expired or revoked.
- 500
Internal error.
Request
curl -X POST https://echosistema.live/api/v1/auth/logout \ -b cookies.txt \ -H "X-XSRF-TOKEN: a1b2c3d4e5f6"
Response 200
{
"message": "Goodbye, Sample User!"
}Try endpoint
Keep session alive
GET/api/v1/auth/keep-aliveSession cookie
Extends the BFF cookie's session and attempts to refresh the Keycloak JWT with the refresh_token held in Redis. No request body. Session validity never depends on Keycloak: a failure there comes back with `jwt: null` and a `warning`, and the session stays extended.
Headers
CookiestringrequiredThe BFF session cookie `echosistema_bff_session`, set by the login. The browser attaches it on its own; with curl, use `-b`.
Responses
- 200
Session extended; jwt refreshed, null with warning, or absent.
- 401
No valid session: cookie missing, expired or revoked.
- 500
Internal error.
Request
curl https://echosistema.live/api/v1/auth/keep-alive \ -b cookies.txt
Response 200
{
"message": "Session extended, Sample User.",
"jwt": {
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.newtoken",
"refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.newrefresh",
"id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.newidtoken",
"token_type": "Bearer",
"expires_in": 300,
"refresh_expires_in": 1800,
"scope": "openid profile email",
"issuer": "https://sso.echosistema.live/realms/echosistema",
"subject": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"provider": { "driver": "keycloak", "name": "Keycloak Default", "kind": "oidc" }
},
"visitor_ip": "203.0.113.42"
}Try endpoint
Effective role and permissions
GET/api/v1/auth/permissionsSession cookie
The SPA's canonical authorization source, since the login stopped sending `permissions`. Returns the user's role on the current platform (resolved from `X-PUBLIC-KEY`) plus the effective permissions in two equivalent shapes: `permissions` as `action.subject` strings and `permissions_formatted` as pairs. The set merges the role's own permissions (approved memberships only) with those granted directly to the user.
Headers
CookiestringrequiredThe BFF session cookie `echosistema_bff_session`, set by the login. The browser attaches it on its own; with curl, use `-b`.
X-PUBLIC-KEYstring (uuid)requiredPublic key identifying the platform.
Accept-LanguagestringResponse language: pt-BR, en, es or gn.
Responses
- 200
The user's effective role and permissions on the current platform.
- 401
No valid session: cookie missing, expired or revoked.
- 500
Internal error.
Request
curl https://echosistema.live/api/v1/auth/permissions \ -b cookies.txt \ -H "X-PUBLIC-KEY: 33333333-3333-3333-3333-333333333333"
Response 200
{
"success": true,
"roles": [
{
"id": 2,
"name": "administrator",
"localized_name": "Administrador",
"platform": {
"uuid": "8f14e45f-ceea-4b8f-8c0e-5a4a1b3d1a2c",
"name": "EchoSistema",
"public_key": "33333333-3333-3333-3333-333333333333"
}
}
],
"permissions": ["destroy.schedule", "index.all", "index.schedule", "show.all"],
"permissions_formatted": [
{ "action": "destroy", "subject": "schedule" },
{ "action": "index", "subject": "all" },
{ "action": "index", "subject": "schedule" },
{ "action": "show", "subject": "all" }
]
}Try endpoint
User profile
GET/api/v1/me/profileBearer (SSO JWT)
Returns the authenticated user's complete profile in data: identity, images in the unified card shape (avatar, banner and profile), roles with permissions, contacts, addresses, nationalities, biography, platform and affiliate.
Headers
AuthorizationstringrequiredKeycloak's SSO JWT, for callers outside the browser that hold a token instead of a session cookie.
X-PUBLIC-KEYstring (uuid)requiredPublic key identifying the platform.
Accept-LanguagestringResponse language: pt-BR, en, es or gn.
Responses
- 200
Complete profile in data.
- 401
No valid session: cookie missing, expired or revoked.
- 403
Insufficient permissions.
- 404
User not found.
- 500
Internal error.
Request
curl https://echosistema.live/api/v1/me/profile \ -H "Authorization: Bearer 1|a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0" \ -H "X-PUBLIC-KEY: 33333333-3333-3333-3333-333333333333" \ -H "Accept-Language: pt-BR"
Response 200
{
"data": {
"uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"echo_uuid": "e1c1h1o1a1b2c3d4e5f6789012345678901234",
"name": "Sample User",
"email": "sample.user@domain.com",
"email_verified_at": "2026-01-15T10:30:00.000000Z",
"slug": "sample-user",
"avatar": {
"unique_id": null,
"uuid": null,
"url": "https://storage.echosistema.live/live/common/images/default-avatar.webp",
"usage": "avatar"
},
"banner": {
"unique_id": null,
"uuid": null,
"url": "https://storage.echosistema.live/live/common/images/default-banner.webp",
"usage": "banner"
},
"profile_image": {
"unique_id": null,
"uuid": null,
"url": "https://storage.echosistema.live/live/common/images/default-profile.webp",
"usage": "profile"
},
"age": null,
"gender": null,
"gender_name": null,
"birthday": null,
"is_banned": false,
"is_foreign": false,
"is_master": false,
"language": "pt-BR",
"currency": "BRL",
"created_at": "2025-11-02T14:05:00.000000Z",
"roles": [
{
"id": 1,
"uuid": "11111111-1111-1111-1111-111111111111",
"name": "guest",
"localized_name": "Convidado",
"permissions": ["complaint.store"]
}
],
"telephone": null,
"contacts": [],
"social_medias": [],
"address": null,
"addresses": [],
"nationalities": [],
"biography": null,
"platform": {
"id": 2,
"uuid": "22222222-2222-2222-2222-222222222222",
"name": "Sample Platform"
},
"affiliate": null,
"identities": [],
"raw": null
}
}Try endpoint
Update password
PUT/api/v1/me/passwordBearer (SSO JWT)
Changes the authenticated user's password: requires the current password, a 6-character minimum and confirmation, and the new one must be different. After the local save, the password is propagated best-effort to the identity provider and to every active IdentityProviderLink, with back-off retries; IdP failures never block the local change, and the plain-text password never reaches logs or queue payloads.
Headers
AuthorizationstringrequiredKeycloak's SSO JWT, for callers outside the browser that hold a token instead of a session cookie.
X-PUBLIC-KEYstring (uuid)requiredPublic key identifying the platform.
Accept-LanguagestringResponse language: pt-BR, en, es or gn.
Body
current_passwordstring (password)requiredCurrent password, verified before the change.
passwordstring (min 6)requiredNew password, 6 characters minimum and different from the current one.
password_confirmationstringrequiredConfirmation, must match the password.
Responses
- 200
Password updated; SSO propagation continues in the background.
- 400
The new password equals the current one.
- 401
No valid session: cookie missing, expired or revoked.
- 422
Validation error in fields or parameters.
- 500
Internal error.
Request
curl -X PUT https://echosistema.live/api/v1/me/password \
-H "Authorization: Bearer 1|a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0" \
-H "X-PUBLIC-KEY: 33333333-3333-3333-3333-333333333333" \
-H "Content-Type: application/json" \
-d '{
"current_password": "currentPassword123",
"password": "newSecurePassword456",
"password_confirmation": "newSecurePassword456"
}'Response 200
{
"message": "Password updated successfully."
}Try endpoint
List countries
GET/api/v1/public/countriesPublic
Paginated country list with filters by ISO code, name, capital, currency, language and timezone. Public route; minimum=true returns only the essential fields, ideal for dropdowns.
Headers
X-PUBLIC-KEYstring (uuid)requiredPublic key identifying the platform.
Accept-LanguagestringResponse language: pt-BR, en, es or gn.
Query
codestring (2)ISO 3166-1 alpha-2 code, exact match.
namestringCountry name, case-insensitive partial match.
cca3string (3)ISO 3166-1 alpha-3 code.
ccn3string (3)ISO 3166-1 numeric code.
ciocstring (3)International Olympic Committee code.
capitalstringCapital city name.
timezonestringTimezone in IANA format.
currencystring (3)ISO 4217 currency code.
languagesstringISO 639-1 language code.
minimumbooleanWhen true, returns only id, uuid, code, name and official_name.
statesstringLoads the states: IDs, names, or empty for all.
has_subdivisionsbooleanFilters by subdivisions: true only countries with states, false only those exposing cities directly.
orderBystringSort field: id, name, code, official_name or created_at.
pageintegerPagination page.
per_pageinteger (1-200)Records per page, 1 to 200.
no_paginatebooleanWhen true, returns everything without pagination.
Responses
- 200
Paginated list in data, with links and meta.
- 422
Validation error in fields or parameters.
- 429
Rate limit exceeded.
- 500
Internal error.
Request
curl "https://echosistema.live/api/v1/public/countries?code=BR" \ -H "X-PUBLIC-KEY: pk_live_abc123def456" \ -H "Accept-Language: pt-BR"
Response 200
{
"data": [
{
"id": 1,
"uuid": "32860919-8031-3f86-89e8-a71e5452bf6f",
"code": "BR",
"name": "Brazil",
"official_name": "Federative Republic of Brazil",
"has_subdivisions": true,
"geolocation": { "latitude": -15.7942, "longitude": -47.8822 },
"details": {
"map": "https://goo.gl/maps/waCKk21HeeqFzkNC9",
"flag": "🇧🇷",
"name": "Brazil",
"codes": { "cca3": "BRA", "ccn3": "076", "cioc": "BRA" },
"region": "Americas",
"borders": ["ARG", "BOL", "COL", "GUF", "GUY", "PRY", "PER", "SUR", "URY", "VEN"],
"capital": "Brasília",
"languages": [{ "code": "por", "name": "Portuguese" }],
"subregion": "South America",
"timezones": ["UTC-05:00", "UTC-04:00", "UTC-03:00", "UTC-02:00"],
"continents": ["South America"],
"currencies": [{ "code": "BRL", "name": "Brazilian real", "symbol": "R$" }],
"postal_code": { "regex": "^(\\d{8})$", "format": "#####-###" },
"coat_of_arms": {
"png": "https://mainfacts.com/media/images/coats_of_arms/br.png",
"svg": "https://mainfacts.com/media/images/coats_of_arms/br.svg"
},
"official_name": "Federative Republic of Brazil"
}
}
],
"links": {
"first": "http://echosistema.dev/api/v1/public/countries?page=1",
"last": "http://echosistema.dev/api/v1/public/countries?page=1",
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 1,
"path": "http://echosistema.dev/api/v1/public/countries",
"per_page": 25,
"to": 1,
"total": 1
}
}Try endpoint
Show country
GET/api/v1/public/countries/{country}Public
Full details of one country. The country parameter takes the ISO alpha-2 code (BR) or the numeric ID. The response carries states with every state when the country has subdivisions; without them, it exposes cities. images and texts eager-load the CDN and CMS relations.
Headers
X-PUBLIC-KEYstring (uuid)requiredPublic key identifying the platform.
Accept-LanguagestringResponse language: pt-BR, en, es or gn.
Path
countrystringrequiredCountry identifier: ISO alpha-2 code (BR) or numeric ID. Verified on staging: UUID and alpha-3 code (BRA) return 500.
Query
minimumbooleanWhen true, returns only id, uuid, code, name and official_name.
imagesbooleanWhen true, eager-loads the images relation (usage mini_card).
textsbooleanWhen true, eager-loads the CMS texts; content follows the title + body convention.
statesstringLoads the states: IDs, names, or empty for all.
Responses
- 200
Country details in data.
- 404
Country not found.
- 429
Rate limit exceeded.
- 500
Internal error.
Request
curl https://echosistema.live/api/v1/public/countries/BR \ -H "X-PUBLIC-KEY: pk_live_abc123def456" \ -H "Accept-Language: pt-BR"
Response 200
{
"data": {
"id": 1,
"uuid": "32860919-8031-3f86-89e8-a71e5452bf6f",
"code": "BR",
"name": "Brazil",
"official_name": "Federative Republic of Brazil",
"has_subdivisions": true,
"geolocation": { "latitude": -15.7942, "longitude": -47.8822 },
"details": {
"map": "https://goo.gl/maps/waCKk21HeeqFzkNC9",
"flag": "🇧🇷",
"name": "Brazil",
"codes": { "cca3": "BRA", "ccn3": "076", "cioc": "BRA" },
"region": "Americas",
"borders": ["ARG", "BOL", "COL", "GUF", "GUY", "PRY", "PER", "SUR", "URY", "VEN"],
"capital": "Brasília",
"languages": [{ "code": "por", "name": "Portuguese" }],
"subregion": "South America",
"timezones": ["UTC-05:00", "UTC-04:00", "UTC-03:00", "UTC-02:00"],
"continents": ["South America"],
"currencies": [{ "code": "BRL", "name": "Brazilian real", "symbol": "R$" }],
"postal_code": { "regex": "^(\\d{8})$", "format": "#####-###" },
"coat_of_arms": {
"png": "https://mainfacts.com/media/images/coats_of_arms/br.png",
"svg": "https://mainfacts.com/media/images/coats_of_arms/br.svg"
},
"official_name": "Federative Republic of Brazil"
},
"states": [
{ "id": 1, "uuid": "43181d2e-7efd-3fb4-a831-f19149e0780b", "abbreviation": "AC", "name": "Acre", "region": "Norte" },
{ "id": 2, "uuid": "beee0aab-324c-3683-bd3b-18c9aeda7948", "abbreviation": "AL", "name": "Alagoas", "region": "Nordeste" },
{ "id": 3, "uuid": "11695e3e-d7f0-3b68-bef0-5a97515ade35", "abbreviation": "AP", "name": "Amapá", "region": "Norte" }
]
}
}Try endpoint
Show state
GET/api/v1/public/countries/{country}/states/{state}Public
Details of a state within a country. The state parameter takes the name, the numeric ID or the UUID; a name with accents and spaces travels URL-encoded. The response carries the nested country and the cities. The 404 also covers a state that does not belong to the given country.
Headers
X-PUBLIC-KEYstring (uuid)requiredPublic key identifying the platform.
Accept-LanguagestringResponse language: pt-BR, en, es or gn.
Path
countrystringrequiredCountry identifier: ISO alpha-2 code (BR) or numeric ID. Verified on staging: UUID and alpha-3 code (BRA) return 500.
statestringrequiredState identifier: name (São Paulo), numeric ID or UUID. Verified on staging: slug (sao-paulo) returns 500 and the abbreviation (SP) returns 404.
Query
imagesbooleanWhen true, eager-loads the images relation (usage mini_card).
textsbooleanWhen true, eager-loads the CMS texts; content follows the title + body convention.
Responses
- 200
State details in data.
- 404
Not found: country, state, or a state that does not belong to the country.
- 422
Validation error in fields or parameters.
- 429
Rate limit exceeded.
- 500
Internal error.
Request
curl "https://echosistema.live/api/v1/public/countries/BR/states/S%C3%A3o%20Paulo" \ -H "X-PUBLIC-KEY: pk_live_abc123def456" \ -H "Accept-Language: pt-BR"
Response 200
{
"data": {
"id": 25,
"uuid": "db073d1d-ebe2-34e8-bf34-4884acdb475e",
"country_id": 1,
"name": "São Paulo",
"abbreviation": "SP",
"region": "Sudeste",
"country": {
"uuid": "32860919-8031-3f86-89e8-a71e5452bf6f",
"name": "Brazil",
"official_name": "Federative Republic of Brazil",
"code": "BR"
},
"cities": [
{
"id": 2180,
"uuid": "b5080cd5-9b2d-38cc-a6ef-7d6dfbfb2e74",
"name": "São Paulo"
}
]
}
}Try endpoint
Show city
GET/api/v1/public/countries/{country}/states/{state}/cities/{city}Public
Details of a city within a state and country, with chained ownership validation. Identifiers take the name, numeric ID or UUID; the response carries the nested country and state.
Headers
X-PUBLIC-KEYstring (uuid)requiredPublic key identifying the platform.
Accept-LanguagestringResponse language: pt-BR, en, es or gn.
Path
countrystringrequiredCountry identifier: ISO alpha-2 code (BR) or numeric ID. Verified on staging: UUID and alpha-3 code (BRA) return 500.
statestringrequiredState identifier: name (São Paulo), numeric ID or UUID. Verified on staging: slug (sao-paulo) returns 500 and the abbreviation (SP) returns 404.
citystringrequiredCity identifier: name (São Paulo), numeric ID or UUID.
Query
textsbooleanWhen true, eager-loads the CMS texts; content follows the title + body convention.
Responses
- 200
City details in data.
- 404
Not found: country, state, city, or a broken link in the chain.
- 422
Validation error in fields or parameters.
- 429
Rate limit exceeded.
- 500
Internal error.
Request
curl "https://echosistema.dev/api/v1/public/countries/BR/states/S%C3%A3o%20Paulo/cities/S%C3%A3o%20Paulo" \ -H "X-PUBLIC-KEY: pk_live_abc123def456" \ -H "Accept-Language: pt-BR"
Response 200
{
"data": {
"id": 2180,
"uuid": "b5080cd5-9b2d-38cc-a6ef-7d6dfbfb2e74",
"state_id": 25,
"country_id": 1,
"name": "São Paulo",
"abbreviation": null,
"country": {
"uuid": "32860919-8031-3f86-89e8-a71e5452bf6f",
"name": "Brazil",
"official_name": "Federative Republic of Brazil",
"code": "BR"
},
"state": {
"uuid": "db073d1d-ebe2-34e8-bf34-4884acdb475e",
"name": "São Paulo",
"abbreviation": "SP",
"region": "Sudeste"
}
}
}Try endpoint
Show city (Shared)
GET/api/v1/cities/{city}Public
The rich city record, outside the countries tree: it resolves by UUID or name and carries country, state, images and the editorial content (titles, topics and description). Verified on staging: it requires X-PUBLIC-KEY, and answers 403 without it.
Headers
X-PUBLIC-KEYstring (uuid)requiredPublic key identifying the platform.
Accept-LanguagestringResponse language: pt-BR, en, es or gn.
Path
citystringrequiredCity identifier: UUID or name, auto-detected by resolveRouteBinding.
Query
languagestringIETF tag filtering titles, topics and description; is_default entries stay included. Without it, everything comes back.
Responses
- 200
City record in data, with the editorial content already filtered.
- 403
Missing or invalid public key.
- 404
Not found: country, state, city, or a broken link in the chain.
- 500
Internal error.
Request
curl "https://echosistema.dev/api/v1/cities/Encarnaci%C3%B3n?language=es" \ -H "X-PUBLIC-KEY: pk_live_abc123def456"
Response 200
{
"data": {
"uuid": "35e51559-f130-31d0-bfb8-95b6c1caabfc",
"name": "Encarnación",
"abbreviation": "ENC",
"country": {
"uuid": "2eb81f74-aded-3702-b132-a7f1ce4bdf05",
"code": "PY",
"name": "Paraguay"
},
"state": {
"uuid": "c5f7a378-0994-319b-8620-809ce6955557",
"name": "Itapuá",
"abb": "IT"
},
"images": [
{
"usage": "card",
"url": "https://storage.echosistema.dev/staging/platform/echosistema/images/card/5a1f2e4d-3180-3d3b-9d60-5401e538ce3d.webp",
"unique_id": "a796787b"
}
],
"titles": [
{
"index": 1,
"uuid": "35e51559-f130-31d0-bfb8-95b6c1caabfc",
"content": "Gestión de Propiedades",
"language": "es",
"is_default": true,
"usage": "city_info",
"details": "Encarnación experimenta un crecimiento inmobiliario acelerado…"
}
],
"topics": [
{
"usage": "cost_of_living",
"language": "es",
"is_default": true,
"title": "Custo de vida",
"body": "<p>Vivir en Encarnación resulta más accesible que en Asunción…</p>",
"icon": "ri-money-dollar-circle-line"
}
],
"description": [
{
"usage": "general_description",
"language": "es",
"is_default": true,
"title": null,
"body": "<p>Encarnación, conocida como La Perla del Sur, es la capital…</p>"
}
]
}
}