Reference index
API Reference
Real endpoints, straight from the API repository's OpenAPI contracts: nothing here is made up. Sanctum authentication 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 Sanctum token in Authorization: Bearer; 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 through HTTP Basic (Base64 email:password) against Sanctum and returns the token at the response root. In parallel it attempts Keycloak SSO: the jwt block may be null without invalidating the login, and the refresh_token is stored encrypted in the server-side Redis for logout, keep-alive and sso-jwt to consume later.
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
devicestringrequiredDevice name labeling the Sanctum token.
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 Sanctum token is always valid, 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" \
-d '{ "device": "web-browser" }'Response 200
{
"message": "User authenticated successfully!",
"token": "1|a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0",
"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 platform and projects the identity into Keycloak. On realestate platforms the agent, professional and customer flags decide the role, in that priority order; with no flag the user comes in as guest, and it is one role per platform. The Sanctum token and jwt block return as in 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.
devicestringrequiredDevice name labeling the Sanctum token.
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/logoutBearer (Sanctum)
Revokes the current Sanctum token and attempts to end the Keycloak session with the refresh_token from the Redis cache, best-effort and with no request body. The response is 200 even when Keycloak fails, and the cache is always cleared.
Headers
AuthorizationstringrequiredSanctum token in Bearer format.
Responses
- 200
Token revoked, best-effort; always 200.
- 401
Missing or invalid bearer.
- 500
Internal error.
Request
curl -X POST https://echosistema.live/api/v1/auth/logout \ -H "Authorization: Bearer 1|a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0"
Response 200
{
"message": "Goodbye, Sample User!"
}Try endpoint
Keep session alive
GET/api/v1/auth/keep-aliveBearer (Sanctum)
Extends the Sanctum session and attempts to refresh the Keycloak JWT from Redis. Three variants: jwt refreshed; jwt null with warning jwt_refresh_failed; or a response without the jwt key when SSO never happened. Sanctum validity never depends on Keycloak.
Headers
AuthorizationstringrequiredSanctum token in Bearer format.
Responses
- 200
Session extended; jwt refreshed, null with warning, or absent.
- 401
Missing or invalid bearer.
- 500
Internal error.
Request
curl https://echosistema.live/api/v1/auth/keep-alive \ -H "Authorization: Bearer 1|a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0"
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
User profile
GET/api/v1/me/profileBearer (Sanctum)
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
AuthorizationstringrequiredSanctum token in Bearer format.
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
Missing or invalid bearer.
- 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 (Sanctum)
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
AuthorizationstringrequiredSanctum token in Bearer format.
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
Missing or invalid bearer.
- 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>"
}
]
}
}