Reference index
API Reference
Real endpoints, straight from the API repository's OpenAPI contracts: nothing here is made up. BFF cookie-session 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 HttpOnly session cookie the login sets - no credential comes back in the body, and neither `token` nor `jwt` exists as a field any more; mutating calls also echo the XSRF-TOKEN cookie as X-XSRF-TOKEN. After a reload, rebuild the user with GET /auth/me instead of asking for the password again. Accept-Language (pt-BR, en, es, gn) translates names and messages.
Server
https://echosistema.live
One origin, this deployment’s: `NUXT_PUBLIC_API_PROD_BASE_URL` in .env, the same one the site uses for sign-in and every other call. Pointing at another environment means changing that variable - and it moves the documentation, the test panel and the application together.
Authenticate user
POST/api/v1/authBasic (email:password)
Authenticates through HTTP Basic (Base64 email:password) and opens a BFF cookie session: the 200 sets echosistema_bff_session (HttpOnly, 7-day absolute TTL) and the readable XSRF-TOKEN. No credential comes back in the body - the response carries neither `token` nor `jwt`. The identity is projected onto Keycloak in the background and the resulting JWT stays on the server; a failure there does not invalidate 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
devicestringrequiredDevice name recorded for audit. It no longer labels a 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 session cookie is set and the body carries the user, with no credential of any kind.
- 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" \
--cookie-jar cookies.txt \
-d '{ "device": "web-browser" }'Response 200
{
"message": "User authenticated successfully!",
"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"
}
],
"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"
}
],
"is_backoffice": false,
"is_service_provider": false
}
},
"visitor_ip": "203.0.113.42"
}Try endpoint
Server
https://echosistema.live
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. It opens the cookie session and returns the jwt block exactly as login does.
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 recorded for audit. It no longer labels a 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"
}
],
"is_backoffice": false,
"is_service_provider": false
}
},
"visitor_ip": "203.0.113.42"
}Try endpoint
Server
https://echosistema.live
Log out
POST/api/v1/auth/logoutSession cookie
Destroys the BFF session, clears the cached Keycloak JWT 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 both cookies are cleared regardless.
Headers
CookiestringrequiredHttpOnly session cookie, set by the login and replayed by the browser. From a browser it is never built by hand: send the call with credentials: 'include'.
X-XSRF-TOKENstringrequiredCSRF double submit: the value of the readable XSRF-TOKEN cookie. Required on POST, PUT, PATCH and DELETE; without it the answer is 419.
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 \ --cookie cookies.txt \ -H "X-PUBLIC-KEY: 33333333-3333-3333-3333-333333333333" \ -H "X-XSRF-TOKEN: eyJpdiI6..."
Response 200
{
"message": "Goodbye, Sample User!"
}Try endpoint
Server
https://echosistema.live
Keep session alive
GET/api/v1/auth/keep-aliveSession cookie
Refreshes the Keycloak JWT from Redis. It does NOT extend the session: the BFF window is absolute and nothing renews it, so a failed refresh never costs the caller its session. Three variants: jwt refreshed; jwt null with warning jwt_refresh_failed; or a response with no jwt key when there never was SSO.
Headers
CookiestringrequiredHttpOnly session cookie, set by the login and replayed by the browser. From a browser it is never built by hand: send the call with credentials: 'include'.
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 \ --cookie cookies.txt \ -H "X-PUBLIC-KEY: 33333333-3333-3333-3333-333333333333"
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
Server
https://echosistema.live
The session's user
GET/api/v1/auth/meSession cookie
Returns the session's user in the SAME shape as login. This is the reload route: the cookie survives, the in-memory data.user does not. It mints no cookie, no token and triggers no Keycloak projection, so calling it on every page load is free of side effects.
Headers
CookiestringrequiredHttpOnly session cookie, set by the login and replayed by the browser. From a browser it is never built by hand: send the call with credentials: 'include'.
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.
Responses
- 200
The session's user, in the same shape as login. No Set-Cookie and no credential.
- 401
Missing or invalid bearer.
- 500
Internal error.
Request
curl https://echosistema.live/api/v1/auth/me \ --cookie cookies.txt \ -H "X-PUBLIC-KEY: 33333333-3333-3333-3333-333333333333" \ -H "Accept-Language: pt-BR"
Response 200
{
"message": "Sample User successfully authenticated!",
"data": {
"user": {
"uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "Sample User",
"email": "sample.user@domain.com",
"avatar": { "url": "https://example.com/avatar.png", "usage": "avatar" },
"language": "pt-BR",
"currency": "BRL",
"roles": [
{
"id": 1,
"platform": {
"uuid": "22222222-2222-2222-2222-222222222222",
"name": "Sample Platform",
"public_key": "33333333-3333-3333-3333-333333333333"
},
"name": "guest",
"localized_name": "Convidado"
}
],
"is_backoffice": false,
"is_service_provider": false
}
},
"visitor_ip": "203.0.113.42"
}Try endpoint
Server
https://echosistema.live
User permissions
GET/api/v1/auth/permissionsSession cookie
The SPA's single source of authorization. Permissions arrive in two projections of the SAME list: permissions (action.scope strings, for programmatic checks) and permissions_formatted (objects, for screens that group by subject). The test is an exact match OR the .all wildcard. Never derive a permission from data.user.roles: a role is scope, not permission.
Headers
CookiestringrequiredHttpOnly session cookie, set by the login and replayed by the browser. From a browser it is never built by hand: send the call with credentials: 'include'.
X-PUBLIC-KEYstring (uuid)requiredPublic key identifying the platform.
Accept-LanguagestringResponse language: pt-BR, en, es or gn.
Responses
- 200
Roles (zero or one, scoped to this platform) and the permission list in two projections.
- 401
Missing or invalid bearer.
- 500
Internal error.
Request
curl https://echosistema.live/api/v1/auth/permissions \ --cookie 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
Server
https://echosistema.live
Forgot password
POST/api/v1/auth/password/forgotPublic
Sends the recovery e-mail. It answers 200 whether or not the address exists, deliberately: telling the two apart would hand over the list of who has an account on the platform. Do not parse the message to infer existence.
Headers
X-PUBLIC-KEYstring (uuid)requiredPublic key identifying the platform.
Accept-LanguagestringResponse language: pt-BR, en, es or gn.
Body
emailstring (email)requiredEmail, unique per platform.
Responses
- 200
Request received. It is 200 even when the address does not exist.
- 422
Validation error in fields or parameters.
- 429
Rate limit exceeded.
- 500
Internal error.
Request
curl -X POST https://echosistema.live/api/v1/auth/password/forgot \
-H "X-PUBLIC-KEY: 33333333-3333-3333-3333-333333333333" \
-H "Content-Type: application/json" \
-d '{ "email": "sample.user@domain.com" }'Response 200
{
"success": true,
"message": "Enviamos seu link de redefinição de senha por e-mail!"
}Try endpoint
Server
https://echosistema.live
Reset password
POST/api/v1/auth/password/resetPublic
Resets the password from the e-mail link. The token and the e-mail come from the link's query (?token= and ?email=) and go back in the body exactly as they arrived. The token is signed, single-use and time-limited; a 400 means ask for a new link, not try again.
Headers
X-PUBLIC-KEYstring (uuid)requiredPublic key identifying the platform.
Accept-LanguagestringResponse language: pt-BR, en, es or gn.
Body
emailstring (email)requiredEmail, unique per platform.
tokenstringrequiredSigned token from the recovery link's ?token=, sent back exactly as it arrived.
passwordstring (min 6)requiredNew password, 6 characters minimum and different from the current one.
password_confirmationstringrequiredConfirmation, must match the password.
Responses
- 200
Password reset; the token was consumed and will not serve again.
- 400
Token already used, expired, or not matching the e-mail. Ask for a new link.
- 422
Validation error in fields or parameters.
- 429
Rate limit exceeded.
- 500
Internal error.
Request
curl -X POST https://echosistema.live/api/v1/auth/password/reset \
-H "X-PUBLIC-KEY: 33333333-3333-3333-3333-333333333333" \
-H "Content-Type: application/json" \
-d '{
"email": "sample.user@domain.com",
"token": "9f2c1a...",
"password": "newSecurePassword456",
"password_confirmation": "newSecurePassword456"
}'Response 200
{
"success": true,
"message": "Senha redefinida com sucesso!"
}Try endpoint
Server
https://echosistema.live
Issue handoff token
POST/api/v1/auth/flash-token/issueSession cookie
Mints a single-use handoff token, valid for 60 seconds, for the current session. It carries a session to another domain of the group without a second password: the cookie is bound to a domain, and this token is the right to open a session on the other origin.
Headers
CookiestringrequiredHttpOnly session cookie, set by the login and replayed by the browser. From a browser it is never built by hand: send the call with credentials: 'include'.
X-XSRF-TOKENstringrequiredCSRF double submit: the value of the readable XSRF-TOKEN cookie. Required on POST, PUT, PATCH and DELETE; without it the answer is 419.
X-PUBLIC-KEYstring (uuid)requiredPublic key identifying the platform.
Body
devicestringDevice name recorded for audit. It no longer labels a token.
Responses
- 200
Token minted, with expires_in always 60.
- 401
Missing or invalid bearer.
- 429
Rate limit exceeded.
- 500
Internal error.
Request
curl -X POST https://echosistema.live/api/v1/auth/flash-token/issue \
--cookie cookies.txt \
-H "X-PUBLIC-KEY: 33333333-3333-3333-3333-333333333333" \
-H "X-XSRF-TOKEN: eyJpdiI6..." \
-H "Content-Type: application/json" \
-d '{ "device": "web-browser" }'Response 200
{
"success": true,
"flash_token": "6791a3b2c4d5e6f7.es3a7b9c1d2e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1",
"expires_in": 60
}Try endpoint
Server
https://echosistema.live
Exchange handoff token
POST/api/v1/auth/flash-tokenPublic
Spends the handoff token and opens a NEW session on this origin. Public because the token is the credential, and CSRF-exempt for the same reason. Carry the token in the URL FRAGMENT (#flash=), never in the query string, and scrub it from the address as soon as it is spent.
Headers
X-PUBLIC-KEYstring (uuid)requiredPublic key identifying the platform.
Accept-LanguagestringResponse language: pt-BR, en, es or gn.
Body
flash_tokenstring (32-512)requiredThe handoff token in plaintext, shaped .es. If you transported it base64-encoded, decode it before sending.
devicestringDevice name recorded for audit. It no longer labels a token.
Responses
- 200
Session opened on this origin; both cookies come back, as in login.
- 401
Token unknown, already spent or expired. It dies on first read, so there is nothing to retry.
- 422
Validation error in fields or parameters.
- 429
Rate limit exceeded.
- 500
Internal error.
Request
curl -X POST https://echosistema.live/api/v1/auth/flash-token \
-H "X-PUBLIC-KEY: 33333333-3333-3333-3333-333333333333" \
-H "Content-Type: application/json" \
--cookie-jar cookies.txt \
-d '{ "flash_token": "6791a3b2c4d5e6f7.es3a7b...", "device": "web-browser" }'Response 200
{
"message": "Sample User successfully authenticated!",
"data": {
"user": {
"uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "Sample User",
"email": "sample.user@domain.com",
"is_backoffice": false,
"is_service_provider": false
}
},
"visitor_ip": "203.0.113.42"
}Try endpoint
Server
https://echosistema.live
User profile
GET/api/v1/me/profileSession cookie
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
CookiestringrequiredHttpOnly session cookie, set by the login and replayed by the browser. From a browser it is never built by hand: send the call with credentials: 'include'.
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 \ --cookie cookies.txt \ -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
Server
https://echosistema.live
Update password
PUT/api/v1/me/passwordSession cookie
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
CookiestringrequiredHttpOnly session cookie, set by the login and replayed by the browser. From a browser it is never built by hand: send the call with credentials: 'include'.
X-XSRF-TOKENstringrequiredCSRF double submit: the value of the readable XSRF-TOKEN cookie. Required on POST, PUT, PATCH and DELETE; without it the answer is 419.
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 \
--cookie cookies.txt \
-H "X-XSRF-TOKEN: eyJpdiI6..." \
-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
Server
https://echosistema.live
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
Server
https://echosistema.live
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
Server
https://echosistema.live
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
Server
https://echosistema.live
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
Server
https://echosistema.live
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>"
}
]
}
}Try endpoint
Server
https://echosistema.live