Skip to content

Authentication

Overview

The Pontotel API uses Bearer Token Authentication (JWT) to authenticate requests.

Authentication Flow

  1. Send credentials to the /login/ endpoint
  2. Receive access_token in the response
  3. Include the token in the Authorization: Bearer {token} header
  4. The token expires in 1 hour

Login Endpoint

POST /api/v4/login/

Request

JSON
1
2
3
4
{
  "username": "your_username",
  "password": "your_password"
}

Response (200 OK)

JSON
1
2
3
{
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
}

Code Examples

Python
import httpx
from datetime import datetime, timedelta, timezone

class PontotelAuth:
    def __init__(self, username, password, base_url):
        self.username = username
        self.password = password
        self.base_url = base_url
        self.token = None
        self.token_expires_at = None

    async def login(self):
        """Log in and obtain a token"""
        url = f"{self.base_url}/login/"
        payload = {
            "username": self.username,
            "password": self.password
        }

        async with httpx.AsyncClient() as client:
            response = await client.post(url, json=payload)
            response.raise_for_status()

        data = response.json()
        self.token = data["access_token"]
        self.token_expires_at = datetime.now(tz=timezone.utc) + timedelta(minutes=60)

        return self.token

    async def get_token(self):
        """Return a valid token, renewing it when needed"""
        if not self.token or datetime.now(tz=timezone.utc) >= self.token_expires_at:
            await self.login()
        return self.token

    async def get_headers(self):
        """Return authenticated headers"""
        return {
            "Authorization": f"Bearer {await self.get_token()}",
            "Content-Type": "application/json"
        }

# Usage
import asyncio

async def main():
    auth = PontotelAuth(
        username="your_username",
        password="your_password",
        base_url="https://apis.pontotel.com.br/pontotel/api/v4"
    )

    # Make requests
    headers = await auth.get_headers()
    async with httpx.AsyncClient() as client:
        response = await client.get(
            "https://apis.pontotel.com.br/pontotel/api/v4/usuarios/",
            headers=headers
        )

asyncio.run(main())
JavaScript
class PontotelAuth {
  constructor(username, password, baseUrl) {
    this.username = username;
    this.password = password;
    this.baseUrl = baseUrl;
    this.token = null;
    this.tokenExpiresAt = null;
  }

  async login() {
    const url = `${this.baseUrl}/login/`;
    const response = await fetch(url, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        username: this.username,
        password: this.password
      })
    });

    if (!response.ok) {
      throw new Error(`Login failed: ${response.status}`);
    }

    const data = await response.json();
    this.token = data.access_token;
    this.tokenExpiresAt = Date.now() + (data.expires_in * 1000);

    return this.token;
  }

  async getToken() {
    if (!this.token || Date.now() >= this.tokenExpiresAt) {
      await this.login();
    }
    return this.token;
  }

  async getHeaders() {
    const token = await this.getToken();
    return {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    };
  }
}

// Usage
const auth = new PontotelAuth(
  'your_username',
  'your_password',
  'https://apis.pontotel.com.br/pontotel/api/v4'
);

// Make requests
const headers = await auth.getHeaders();
const response = await fetch(
  'https://apis.pontotel.com.br/pontotel/api/v4/usuarios/',
  { headers }
);
Bash
# 1. Log in
curl -X POST "https://apis.pontotel.com.br/pontotel/api/v4/login/" \
  -H "Content-Type: application/json" \
  -d '{
    "username": "your_username",
    "password": "your_password"
  }' \
  | jq -r '.access_token' > token.txt

# 2. Use token
TOKEN=$(cat token.txt)

curl -X GET "https://apis.pontotel.com.br/pontotel/api/v4/usuarios/" \
  -H "Authorization: Bearer $TOKEN"

Security

Important Practices

  • Never share credentials or tokens
  • Store tokens in environment variables or secret managers
  • Rotate credentials regularly
  • Use HTTPS at all times (required)
  • Do not commit tokens to Git

Safe Storage

Python
# .env
PONTOTEL_USERNAME=your_username
PONTOTEL_PASSWORD=your_password

# code
import os

auth = PontotelAuth(
    username=os.environ.get("PONTOTEL_USERNAME"),
    password=os.environ.get("PONTOTEL_PASSWORD"),
    base_url="https://apis.pontotel.com.br/pontotel/api/v4"
)
JavaScript
// .env
PONTOTEL_USERNAME=your_username
PONTOTEL_PASSWORD=your_password

// code
require('dotenv').config();

const auth = new PontotelAuth(
  process.env.PONTOTEL_USERNAME,
  process.env.PONTOTEL_PASSWORD,
  'https://apis.pontotel.com.br/pontotel/api/v4'
);

Expiration and Renewal

  • Tokens expire in 1 hour (3600 seconds)
  • Handle 401 Unauthorized errors by authenticating again
  • Implement automatic renewal logic based on the token exp attribute

Retry Logic Example

Python
import httpx

transport = httpx.AsyncHTTPTransport(retries=3)

async def realizar_requisicao_com_retentativa(url, headers):
    async with httpx.AsyncClient(transport=transport) as client:
        response = await client.get(url, headers=headers)
        response.raise_for_status()
        return response

# Usage
import asyncio

async def main():
    response = await realizar_requisicao_com_retentativa(url, headers)

asyncio.run(main())

Common Errors

Code Error Solution
400 Bad Request Check the payload format
401 Unauthorized Invalid credentials or expired token
403 Forbidden No permission to access the resource
422 Validation error Check the data sent in the payload

Next Steps