Dropzon Public API
Integrate DZ Address lookup, Dropzon location search, package tracking, “Sign in with Dropzon” OAuth, and more into your applications. Built for e-commerce platforms, logistics companies, and developers.
Quick Start
Get your API key
Sign in to the Developer Console and create an API key. Any Dropzon account can access the console.
Authenticate your requests
Include your API key in every request header.
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://api.dropzon.app/api/v1/addresses/lookup?code=DZ%23001-01"Start building
Explore the endpoints below. All responses are JSON. Rate limit: 100 requests/minute per key.
Authentication
All API requests require authentication using a Bearer token in the Authorization header.
Authorization: Bearer YOUR_API_KEYRate Limit
100 requests / minute
Per API key. Burst-friendly with sliding window.
Response Format
JSON (application/json)
All responses include a success boolean.
Error Handling
Errors follow a consistent format with HTTP status codes and descriptive messages.
{
"success": false,
"error": "Invalid or expired API key",
"code": "AUTH_INVALID"
}| Status | Code | Description |
|---|---|---|
| 400 | BAD_REQUEST | Missing or invalid parameters |
| 401 | AUTH_INVALID | Invalid or missing API key |
| 403 | FORBIDDEN | Insufficient permissions for this resource |
| 404 | NOT_FOUND | Resource not found |
| 429 | RATE_LIMITED | Too many requests - slow down |
| 500 | INTERNAL_ERROR | Something went wrong on our end |
Addresses
Look up, search, and validate DZ Addresses. Search by DZ# code, full DZ code, or full address string. You can pass the query as a query parameter (?q=...) or directly in the URL path (/search/DZ%23001-01). Ideal for e-commerce checkout integrations.
Dropzons
Search for Dropzon locations, look up full address details for e-commerce checkout, and find the nearest pickup points.
Tracking
Track packages by tracking number and get real-time status updates for shipments.
Locations
Access the Dropzon location hierarchy - countries, regions, cities, and municipalities where Dropzon operates.
Webhooks
Register webhook URLs to receive real-time notifications when package statuses change or deliveries are completed.
Sign in with Dropzon
OAuth 2.0 Authorization Code with PKCE
Overview
“Sign in with Dropzon” lets your users authenticate using their Dropzon account. After authorization, your app receives an access token that can be used to read the user's profile, email, phone, and DZ Address information - depending on the scopes you request.
The implementation follows the OAuth 2.0 Authorization Code flow with optional PKCE (Proof Key for Code Exchange) for public clients like mobile apps and SPAs.
Setup
Create an OAuth app
Go to the Developer Console → OAuth Apps and create a new OAuth application.
Save your credentials
Copy your client_id (starts with dzo_) and client_secret (starts with dzs_). The secret is only shown once at creation time.
Register redirect URIs
Add one or more callback URLs where users will be redirected after authorization. Must be HTTPS in production (http://localhost is allowed for development).
Available Scopes
Request only the scopes your application needs. Users will see a list of requested permissions on the consent screen.
| Scope | Description |
|---|---|
profile | Name and avatar |
email | Email address |
phone | Phone number |
address | Primary DZ Address |
addresses | All DZ Addresses |
Authorization Flow
Redirect user to Dropzon
Redirect the user's browser to the Dropzon authorization page with your app's parameters.
GET https://dropzon.app/oauth/authorize?
client_id=dzo_your_client_id
&redirect_uri=https://yourapp.com/callback
&response_type=code
&scope=profile email
&state=random_csrf_token
&code_challenge=S256_hash_of_verifier # optional, for PKCE
&code_challenge_method=S256 # optional, for PKCE| Parameter | Description |
|---|---|
client_id | Your OAuth app client ID (dzo_ prefix) |
redirect_uri | Must match a registered redirect URI |
response_type | Must be "code" |
scope | Space-separated scopes (defaults to "profile") |
state | Random string to prevent CSRF attacks |
code_challenge | PKCE challenge (S256 hash of code_verifier) |
code_challenge_method | Must be "S256" when using PKCE |
User signs in and approves
The user sees a consent screen showing your app name, description, and the permissions you're requesting. If they're not logged in, they'll sign in first. After approving, Dropzon redirects them back to your redirect_uri with an authorization code.
Handle the callback
Dropzon redirects the user back to your app with a code and state parameter. Verify the state matches what you sent.
https://yourapp.com/callback?code=AUTH_CODE_HERE&state=random_csrf_tokenIf the user denies access, you'll receive ?error=access_denied&state=... instead. Always check for the error parameter first.
Exchange code for tokens
Make a server-side POST request to exchange the authorization code for an access token and refresh token. This request must include your client_secret - never expose it in frontend code.
curl -X POST https://api.dropzon.app/api/oauth/token \
-H "Content-Type: application/json" \
-d '{
"grant_type": "authorization_code",
"code": "AUTH_CODE_HERE",
"redirect_uri": "https://yourapp.com/callback",
"client_id": "dzo_your_client_id",
"client_secret": "dzs_your_client_secret",
"code_verifier": "original_pkce_verifier" // only if using PKCE
}'Response
{
"success": true,
"data": {
"access_token": "dza_...",
"refresh_token": "dzr_...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "profile email"
}
}Get user info
Use the access token to fetch the authenticated user's profile. The response varies based on the granted scopes.
curl https://api.dropzon.app/api/oauth/userinfo \
-H "Authorization: Bearer dza_your_access_token"Response (with profile + email scopes)
{
"success": true,
"data": {
"sub": "user-uuid-here",
"name": "John Mwangi",
"avatar_url": null,
"role": "user",
"email": "john@example.com",
"email_verified": true
}
}Token Management
Token Lifetimes
Access Token
1 hour
Prefix: dza_
Refresh Token
30 days
Prefix: dzr_
Refreshing Tokens
When the access token expires, use the refresh token to get a new pair. The old refresh token is rotated (invalidated) and a new one is returned.
curl -X POST https://api.dropzon.app/api/oauth/token \
-H "Content-Type: application/json" \
-d '{
"grant_type": "refresh_token",
"refresh_token": "dzr_your_refresh_token",
"client_id": "dzo_your_client_id",
"client_secret": "dzs_your_client_secret"
}'Revoking Tokens
Revoke an access or refresh token when the user logs out of your app. Per RFC 7009, this endpoint always returns 200.
curl -X POST https://api.dropzon.app/api/oauth/revoke \
-H "Content-Type: application/json" \
-d '{ "token": "dza_or_dzr_token_here" }'Complete Example- Node.js / Express
const express = require('express');
const crypto = require('crypto');
const app = express();
const CLIENT_ID = 'dzo_your_client_id';
const CLIENT_SECRET = 'dzs_your_client_secret';
const REDIRECT_URI = 'https://yourapp.com/callback';
const OAUTH_AUTHORIZE = 'https://dropzon.app/oauth'; // consent screen (frontend)
const OAUTH_API = 'https://api.dropzon.app/api/oauth'; // token + userinfo (API)
// Step 1: Redirect to Dropzon
app.get('/login', (req, res) => {
const state = crypto.randomBytes(16).toString('hex');
req.session.oauthState = state;
const params = new URLSearchParams({
client_id: CLIENT_ID,
redirect_uri: REDIRECT_URI,
response_type: 'code',
scope: 'profile email',
state,
});
res.redirect(OAUTH_AUTHORIZE + '/authorize?' + params);
});
// Step 3-4: Handle callback and exchange code
app.get('/callback', async (req, res) => {
const { code, state, error } = req.query;
if (error) return res.send('Authorization denied');
if (state !== req.session.oauthState) return res.status(403).send('Invalid state');
// Exchange code for tokens
const tokenRes = await fetch(OAUTH_API + '/token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
grant_type: 'authorization_code',
code,
redirect_uri: REDIRECT_URI,
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
}),
});
const { data: tokens } = await tokenRes.json();
// Step 5: Fetch user info
const userRes = await fetch(OAUTH_API + '/userinfo', {
headers: { Authorization: 'Bearer ' + tokens.access_token },
});
const { data: user } = await userRes.json();
// user = { sub, name, email, ... }
req.session.user = user;
res.redirect('/dashboard');
});Endpoint Reference
| Method | Endpoint | Auth |
|---|---|---|
| GET | /oauth/authorize | None |
| POST | /oauth/token | None |
| GET | /oauth/userinfo | Bearer (access token) |
| POST | /oauth/revoke | None |
Security Best Practices
Always validate the state parameter
Compare the state in the callback with the one you sent to prevent CSRF attacks.
Keep client_secret server-side
Never expose your client secret in frontend JavaScript, mobile app binaries, or version control.
Use PKCE for public clients
Single-page apps and mobile apps should use PKCE (code_challenge + code_verifier) since they cannot securely store a client_secret.
Use HTTPS redirect URIs
Always use HTTPS for redirect URIs in production. HTTP is only allowed for localhost during development.
Request minimal scopes
Only request the scopes your application actually needs. Users are more likely to approve fewer permissions.
Handle token expiry gracefully
Use the refresh token flow to renew access tokens. If the refresh token is also expired, redirect the user to re-authorize.
Sign in with Dropzon - Button
Add a branded “Sign in with Dropzon” button to your app. Pick a variant and size below, then copy the code.
Variant
Size
<a href="https://dropzon.app/oauth/authorize?client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&response_type=code&scope=profile email&state=RANDOM_STATE"
style="display:inline-flex;align-items:center;gap:10px;height:44px;padding:0 20px;background:#0d84d4;color:#fff;border:none;border-radius:12px;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;font-size:14px;font-weight:600;text-decoration:none;cursor:pointer;transition:opacity 0.15s;"
onmouseover="this.style.opacity='0.9'" onmouseout="this.style.opacity='1'">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none"><path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7z" fill="#ffffff"/><circle cx="12" cy="9" r="2.5" fill="white"/></svg>
Sign in with Dropzon
</a>Branding Guidelines
Use the provided Dropzon pin icon next to the text
Use "Sign in with Dropzon" as the button label
Match one of the four official variants above
Do not stretch, skew, or modify the pin icon
Do not change the button text to other wording
Do not use a font size smaller than 14px
Ready to integrate?
Get your API key and start building with the Dropzon address network. Free tier available for development and testing.