docs.c0.lt

Auth

Authentication

The wholesale voice API uses bearer JWTs. The wholesale platform is currently in private beta, so new accounts go through a magic-link first-login flow after our team approves the signup request. The sections below walk through the complete flow with copy-pasteable curl examples.

  1. 1. Request access (beta signup)

    The beta queue lives behind a signup endpoint. Our team reviews each request and replies via email. Replace EMAIL with the contact address that should receive the magic link.

    curl -X POST https://api.c0.lt/v1/signup \
      -H 'content-type: application/json' \
      -d '{
        "email": "EMAIL",
        "company": "Acme Telecom Ltd",
        "expected_volume": "lt-domestic, ~5k mins/mo"
      }'

    On success: HTTP 202 with { "signup_id": "..." }. The email arrives once our team approves.

  2. 2. Redeem the magic link

    The magic-link email lands you on the portal. The portal redeems the token and persists a session locally. If you want to script the first-login from your own code, redeem the token directly:

    curl -X POST https://api.c0.lt/v1/auth/magic-link/redeem \
      -H 'content-type: application/json' \
      -d '{ "token": "MAGIC_LINK_TOKEN_FROM_EMAIL" }'

    On success: HTTP 200 with { "access_token": "...", "refresh_token": "...", "expires_in": 900 }.

  3. 3. Call a protected endpoint

    Send the access_token in the Authorization header as a bearer credential. The example below fetches your current account.

    curl https://api.c0.lt/v1/me \
      -H 'authorization: Bearer ACCESS_TOKEN'

    On success: HTTP 200 with { "user": { "id": "...", "email": "...", "roles": ["customer"] }, "account": { ... } }.

  4. 4. Refresh the access token

    Access tokens expire after 15 minutes. Refresh tokens last 30 days and rotate on every refresh - the response includes a new refresh token, and the previous one is invalidated immediately.

    curl -X POST https://api.c0.lt/v1/auth/refresh \
      -H 'content-type: application/json' \
      -d '{ "refresh_token": "REFRESH_TOKEN" }'

    Store the new refresh token and discard the old one on every call.

  5. JWT shape

    The access token is an HS256 JWT (signing secret rotated server-side, never exposed). Claims:

    • sub: user id (UUID)
    • acc: account id (UUID)
    • roles: array of customer | admin | support
    • iat / exp: standard JWT timestamps; exp - iat = 900 seconds
    • jti: token id for server-side revocation lookups
  6. Idempotency-Key (required for mutating endpoints)

    Every mutating endpoint that touches money, provisioning, or upstream carriers requires a client-generated Idempotency-Key header. We store the first response for 24 hours and replay it on retry. See the reference for the per-endpoint requirement.

    curl -X POST https://api.c0.lt/v1/numbers/order \
      -H 'authorization: Bearer ACCESS_TOKEN' \
      -H 'content-type: application/json' \
      -H 'idempotency-key: 9b5c2e3a-4d7e-4f8a-9b6c-1a2b3c4d5e6f' \
      -d '{
        "country": "LT",
        "type": "geographic",
        "area_code": "5"
      }'

    Use a UUID v4 per logical operation. Same key + same body returns the original response; same key + different body returns HTTP 409.

  7. Sign out

    Sign-out revokes the refresh token. The access token continues to work until exp (max 15 minutes); call this endpoint before discarding both.

    curl -X POST https://api.c0.lt/v1/auth/sign-out \
      -H 'authorization: Bearer ACCESS_TOKEN'