Advancer.World API Documentation
Overview
The Advancer.World REST API lets your organization connect its own systems to its programs, users and partner information. All requests and responses use JSON.
An administrator of your organization generates the API key on the My Organization page.
https://advancer.world/api/v1/customerOpenAPI description:
https://advancer.world/api/v1/openapi.json
— import it into Postman, Insomnia or a client generator.
Authentication
Every request needs your organization's API key and its secret. The secret is shown only once, when the key is generated: store it securely. Generating a new key replaces the previous one, which stops working at once.
Headers Required
| Header | Description |
|---|---|
X-API-Key |
Your API key |
X-API-Secret |
The key's secret (shown only once, when the key was generated) |
Example Request
curl -X GET "https://advancer.world/api/v1/customer/me" \
-H "X-API-Key: your-api-key" \
-H "X-API-Secret: your-api-secret"
Conventions
Response envelope
Every response has the same shape: success, message and data.
Lists add page; failures add error with a stable code you can
branch on. All timestamps are UTC (ISO 8601, ending in Z).
{
"success": false,
"message": "The resource does not exist or you do not have access to it.",
"data": null,
"error": {
"code": "not_found",
"traceId": "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01"
}
}
Quote the traceId if you contact support about a failed request.
Paging
List endpoints return one page at a time, ordered by id. Pass limit (1–100) and,
for the next pages, the cursor from page.nextCursor. When
page.hasMore is false you have reached the end. Cursors are only valid for the same
endpoint and filters; otherwise the API answers 400 invalid_cursor.
GET /api/v1/customer/programs?limit=50
GET /api/v1/customer/programs?limit=50&cursor=eyJWIjoxLCJLIjo1MCwiRiI6IjNhN2JkM2U0NWZiMiJ9
{
"success": true,
"message": null,
"data": [ ... ],
"page": {
"limit": 50,
"hasMore": true,
"nextCursor": "eyJWIjoxLCJLIjo1MCwiRiI6IjNhN2JkM2U0NWZiMiJ9"
}
}
Rate limits
Limits apply per organization, whatever the number of keys: 120 read requests and 30 write requests
per minute, and 20,000 requests per 24 hours. Above a limit the API answers 429 with
rate_limited or quota_exceeded and a Retry-After header giving the
seconds to wait. GET /api/v1/customer/me returns the limits that apply to you.
Invitations have their own limit: 200 per 24 hours (partner invitations, their resends and user
invitations), then 429 invitation_limit_reached.
Writing safely
-
Dry runs. Enrollments, their removal and resends, and user invitations accept
dryRun(in the body, or as a query parameter forDELETEand resends). The API checks everything and answers with what would happen, without changing anything or sending anything. -
Retries.
POSTcalls accept anIdempotency-Keyheader: a unique value per operation, such as a UUID. For 24 hours, a request with the same key gets the first successful response again, with anIdempotent-Replayed: trueheader, instead of repeating the operation. The same key with a different request gets422 idempotency_key_reused.PUTandDELETEare safe to repeat as they are. -
E-mails. Nobody receives two invitation e-mails within 2 hours. The response says
what happened in
emailStatus:sent,failed,not_requested(you sentnotify: false),skipped_recently_contacted,no_recipient,would_send(dry run) ornone. - History. Every change made through the API is recorded as made by the API, with the key that made it.
Endpoints
/api/v1/customer/me
Get Caller
Returns your organization, the key in use and the limits that apply. Useful to test a key.
Example Response
{
"success": true,
"message": null,
"data": {
"customer": { "id": 12, "organizationName": "Acme Corporation" },
"apiKey": {
"id": 5,
"createdAt": "2026-09-28T09:12:00Z",
"lastUsedAt": "2026-09-28T10:00:00Z"
},
"limits": { "readPerMinute": 120, "writePerMinute": 30, "dailyQuota": 20000, "maxPageSize": 100 }
}
}
/api/v1/customer/info
Get Customer Information
Returns information about your organization.
Response Fields
| Field | Type | Description |
|---|---|---|
organizationName | string | Organization name |
contactEmail | string | Administrator email |
contactPhone | string? | Phone number |
streetAddress | string | Street address |
postalCode | string | ZIP/Postal code |
cityName | string | City |
countryName | string | Country |
Example Response
{
"success": true,
"message": null,
"data": {
"organizationName": "Acme Corporation",
"contactEmail": "admin@acme.com",
"contactPhone": "+1-555-0123",
"streetAddress": "123 Main Street",
"postalCode": "10001",
"cityName": "New York",
"countryName": "United States"
}
}
/api/v1/customer/programs
Get Programs
Returns your organization's programs, 100 per page by default (see Paging).
Response Fields (per program)
| Field | Type | Description |
|---|---|---|
id | integer | Program identifier |
title | string | Program name |
summary | string? | Short description |
createdDate | datetime | Creation date (UTC) |
enabled | boolean | Active status |
mode | string | How partners move between states: self_assessment, automatic or manual |
Example Response
{
"success": true,
"message": null,
"data": [
{
"id": 1,
"title": "Sustainability Program",
"summary": "Environmental initiatives for partners",
"createdDate": "2024-01-15T10:30:00Z",
"enabled": true,
"mode": "self_assessment"
}
],
"page": { "limit": 100, "hasMore": false, "nextCursor": null }
}
/api/v1/customer/programs/search?q={query}
Search Programs
Returns programs whose name contains the search term (case-insensitive), paged like Get Programs.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
q | string | Search term, 1–100 characters (required) |
limit, cursor | See Paging |
Example Request
GET /api/v1/customer/programs/search?q=child
/api/v1/customer/users
Get Users
Returns the users of your organization, including inactive ones, 100 per page by default.
Response Fields (per user)
| Field | Type | Description |
|---|---|---|
id | integer | User identifier |
fullName | string | User's full name |
emailAddress | string | Email address |
phone | string? | Phone number |
registrationDate | datetime? | Date of registration (UTC) |
enabled | boolean | Active status |
jobTitle | string? | Position/role |
lastAccessDate | datetime? | Last login (UTC) |
isAdministrator | boolean | Customer admin flag |
preferredLanguage | string? | User's language preference |
Example Response
{
"success": true,
"message": null,
"data": [
{
"id": 42,
"fullName": "John Smith",
"emailAddress": "john.smith@acme.com",
"phone": "+1-555-0124",
"registrationDate": "2024-02-10T09:00:00Z",
"enabled": true,
"jobTitle": "Program Manager",
"lastAccessDate": "2024-11-20T14:30:00Z",
"isAdministrator": true,
"preferredLanguage": "English"
}
],
"page": { "limit": 100, "hasMore": false, "nextCursor": null }
}
/api/v1/customer/users/search?q={query}
/api/v1/customer/users/{email}
Update User
Updates a user of your organization, found by email address. Only the fields you send are changed.
PATCH /users/{userId} does the same
by user id (see Users).
Path Parameters
| Parameter | Type | Description |
|---|---|---|
email | string | Current email address of the user to update |
Request Body (JSON)
| Field | Type | Description |
|---|---|---|
fullName | string? | New full name (max 255) |
emailAddress | string? | A new address doesn't change the login at once. The new address gets a confirmation link (valid 48 hours) and the current one a notice; the response shows the new address as pendingEmailAddress until the link is opened. At most one new address every 2 hours (409 resend_too_soon); an address used by another account gets 409 email_unavailable. |
phone | string? | New phone number (max 20; an empty string clears it) |
jobTitle | string? | New job title (max 50; an empty string clears it) |
Example Request
PUT /api/v1/customer/users/john.smith@acme.com
Content-Type: application/json
{
"fullName": "John David Smith",
"jobTitle": "Senior Program Manager"
}
Example Response
{
"success": true,
"message": null,
"data": {
"message": "User updated successfully"
}
}
/api/v1/customer/programs/{programId}/partners
Get Program Partners
Returns the partners linked to one of your programs, including invitations not yet accepted, 100 per page by default.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
programId | integer | The program ID (from Get Programs endpoint) |
Response Fields (per partner)
| Field | Type | Description |
|---|---|---|
id | integer | Partner identifier |
organizationName | string | Partner organization name |
category | string | Partner type/category |
contactEmail | string | Admin email |
contactPhone | string? | Phone number |
streetAddress | string | Address |
postalCode | string | ZIP/Postal code |
cityName | string | City |
countryName | string | Country |
registrationDate | datetime? | Registration date (UTC); null until the partner registers |
enabled | boolean | Active status |
status | string | invited until the partner registers, then registered |
enrollment | object | invitedAt, viewedAt, acceptedAt for this program (UTC; null when it hasn't happened) |
Example Response
{
"success": true,
"message": null,
"data": [
{
"id": 7,
"status": "registered",
"enrollment": { "invitedAt": "2024-02-20T09:00:00Z", "viewedAt": "2024-02-21T08:15:00Z", "acceptedAt": "2024-02-21T08:16:00Z" },
"organizationName": "Green Solutions Ltd",
"category": "Supplier",
"contactEmail": "contact@greensolutions.com",
"contactPhone": "+44-20-1234-5678",
"streetAddress": "456 Eco Way",
"postalCode": "EC1A 1BB",
"cityName": "London",
"countryName": "United Kingdom",
"registrationDate": "2024-03-01T12:00:00Z",
"enabled": true
}
],
"page": { "limit": 100, "hasMore": false, "nextCursor": null }
}
Programs & Progress
A program is a grid: stages (maturity levels, in order) × subtopics
(grouped in topics). Each cell is a state; a partner has one current state per subtopic.
A transition is the step from one state to the next and carries the work (initiatives,
surveys, signatures, uploads). The program's mode says how partners move:
self_assessment, automatic (when a step's work is complete) or manual.
Field-level details are in the OpenAPI description.
| Endpoint | Returns |
|---|---|
GET /programs/{programId} | The program, its stages, topics and subtopics (ids, names, order) and live counts |
GET /programs/{programId}/structure | The states and transitions as ids, with the number of work items on each transition |
GET /programs/{programId}/progress | How enrolled partners are spread over the stages, overall and per subtopic |
GET /programs/{programId}/partners/progress | Per partner: subtopics positioned, average and lowest stage, last activity (paged) |
GET /programs/{programId}/partners/{partnerId}/progress | A partner's scorecard: current state per subtopic and the next step with the status of each initiative, survey, signature and upload, plus awards |
Descriptions, survey questions and files are not part of the API.
Partners
Partners are the organizations enrolled in at least one of your programs. A partner may also work with other organizations; you only see its enrollments and awards in your programs.
| Endpoint | Returns |
|---|---|
GET /partners?q=&programId=&status= | Your partners, filtered by text (name or e-mail), program or status (invited, registered); paged |
GET /partners/{partnerId} | Profile, enrollments in your programs and awards received in your programs |
KPIs & Awards
| Endpoint | Returns |
|---|---|
GET /kpis | Your KPI definitions (paged) |
GET /programs/{programId}/kpis | Per KPI and state: partners reporting, average, minimum, maximum and standard deviation, or the share of yes for qualitative KPIs |
GET /programs/{programId}/partners/{partnerId}/kpis | The partner's latest KPI values in the program |
GET /programs/{programId}/awards | Award definitions: validity, conditions and how many partners received each |
GET /programs/{programId}/awards/grants?awardId=&partnerId= | Awards granted, whether still valid, and the public verification link (paged) |
Enrollments
Adds partners to your programs and removes them. A partner
that already works with you (it is in one of your programs) and has registered joins at
once, and its administrators are told (outcome: enrolled). Any other partner is
invited (outcome: invited): a new partner is created and e-mailed a
registration link; a registered partner you don't work with yet is e-mailed an invitation. Invited
partners show as invited until they register.
| Endpoint | Does |
|---|---|
POST /programs/{programId}/enrollments | Enrolls or invites a partner. Body: email or partnerId, notify (default true), dryRun. Enrolling a partner already in the program changes nothing (outcome: already_enrolled). |
DELETE /programs/{programId}/enrollments/{partnerId}?notify=&dryRun= | Ends the enrollment and tells the partner's administrators. The partner's positions, answers and other progress are kept, and come back if it is enrolled again. |
POST /programs/{programId}/enrollments/{partnerId}/invitation?dryRun= | Sends a pending invitation again, with a new link (older links stop working). 409 already_accepted once the partner joined. |
Example
POST /api/v1/customer/programs/12/enrollments
Idempotency-Key: 7d1f9c2e-1b7a-4f4e-9a55-0c2a0b6f3e11
Content-Type: application/json
{ "email": "admin@greensolutions.com" }
{
"success": true,
"message": null,
"data": {
"outcome": "invited",
"dryRun": false,
"programId": 12,
"partnerId": 431,
"partnerName": "",
"partnerStatus": "invited",
"enrollment": { "invitedAt": "2026-09-28T14:05:00Z", "viewedAt": null, "acceptedAt": null },
"emailStatus": "sent"
}
}
An address that belongs to an Advancer user who isn't a partner administrator gets
409 email_unavailable; a partnerId outside your programs gets
404 not_found.
Positions
Sets where a partner stands in a subtopic, in manual-mode programs only: in
self-assessment programs partners place themselves, and in automatic ones completing the work moves
them (409 program_mode_not_manual). Both
calls can be repeated safely: the response says whether anything changed.
| Endpoint | Does |
|---|---|
PUT /programs/{programId}/partners/{partnerId}/positions/{subTopicId} | Body { "stateId": 51 }: places the partner at that state of the subtopic, replacing its current one. The states of each subtopic are in GET /programs/{programId}/structure; a state of another subtopic gets 422 validation_failed. |
DELETE /programs/{programId}/partners/{partnerId}/positions/{subTopicId} | Removes the partner's position in the subtopic. |
Users
| Endpoint | Does |
|---|---|
GET /users/{userId} | One user of your organization, with pendingEmailAddress while a new address waits for confirmation. |
POST /users/invitations | Body: email, optional fullName, dryRun. E-mails an invitation to join your organization; invited users are never administrators. An address already invited that hasn't registered gets the invitation again (outcome: invitation_resent). |
PATCH /users/{userId} | Same fields and rules as Update User. |
A registered user of your organization gets 409 already_registered; an address that
belongs to another Advancer account gets 409 email_unavailable.
/api/v1/customer/activity
What changed in your programs, oldest first: position.set, position.cleared,
initiative.progress, kpi.value_set, award.granted,
enrollment.invited, enrollment.accepted and enrollment.removed.
Each event carries ids and names, the new and previous stage for positions, the value for progress and
KPIs, and who made the change (source: partner, customer, automatic, job or api). Paged,
50 per page by default.
| Parameter | Description |
|---|---|
since, until | The period, in ISO 8601 (UTC). At most 90 days per request; default the last 7 days. |
programId, partnerId | Only this program or partner. |
types | Comma-separated event types, e.g. position.set,award.granted. |
The history is recorded since this feature was released; earlier changes are not in it. To keep a
system in step, call it with since set to the time of your last call.
/api/v1/customer/programs/{programId}/trends?interval=&from=&to=
How a program evolves, per week (default; weeks start on Monday) or month:
position changes, advances and setbacks, active partners, initiatives completed, KPI values reported,
awards granted and partners invited, joined or removed. Each period also gives the positions per stage
at its end, and their average stage order, for the partners enrolled today.
Default: the last 12 weeks or 12 months; at most 53 weeks or 24 months per request. Periods before
historyStartsAt are incomplete, because the history didn't exist yet.
/api/v1/customer/programs/{programId}/partners/{partnerId}/kpis/{kpiId}
Records the value a partner reports for a KPI on one state, replacing what it had there.
Body: { "stateId": 12, "value": 42.5 }. Repeating the same value changes nothing
(changed: false). For a qualitative KPI anything other than 0 means yes.
In the web app only the partner can enter this. Recording it here is done
on the partner's behalf, and the progress history keeps who did it — the event's
source is api and it carries the user, so a value your organization entered stays
distinguishable from one the partner entered itself.
The response carries the KPI's targetValue when it has one, but no pass or
fail: nothing in Advancer records whether a higher or a lower number is better, so for an
indicator like a poverty rate a computed verdict would be backwards.
/api/v1/customer/programs/{programId}/partners/{partnerId}/initiatives/{initiativeId}
Records how far a partner has got on an initiative. Body: { "progress": 100 }, with an
optional startedOn (yyyy-MM-dd). Progress runs 0 to 100.
In an automatic-mode programme this can complete a transition and move the partner
to the next stage, exactly as doing the work in the web app would;
positionChanged says whether it did, and the scorecard shows where they are now.
/api/v1/customer/programs/{programId}/work?type=&transitionId=&subTopicId=&q=
The work that moves partners through a program: every initiative,
survey, signature request and upload request, with
the transition it belongs to, the subtopic and stages it sits between, and a rollup of how
the enrolled partners stand on it — a survey's responded, an initiative's
averageProgress, a signature's counts per status.
Every count is out of enrolledPartners, which the response states. Uploads report no
complete, because they never count towards completing a transition.
This is the view the scorecard cannot give: a scorecard reports only a partner's next transition, so an item that partner has already passed does not appear in it.
/api/v1/customer/programs/{programId}/transitions/{transitionId}/work
One transition, partner by partner: who has answered a survey, who has uploaded a file, how far each partner has got on each initiative, and who has completed the transition.
rollup covers every enrolled partner; partners is a page of them, 50 at a
time. A transition belonging to another program, or to another organization, answers 404.
Error Handling
The API uses standard HTTP status codes. Failed requests also return error.code
(see Response envelope); validation errors list the problems in
error.details. A resource of another organization is reported as not found.
| Status | error.code |
Meaning |
|---|---|---|
200 | Success | |
400 | validation_failed, invalid_cursor | The request is not valid; see error.details |
401 | unauthorized | Missing or invalid API credentials |
404 | not_found | The resource doesn't exist or belongs to another organization |
405 | method_not_allowed | The HTTP method isn't supported for this resource |
409 | program_mode_not_manual | Positions can only be set in manual-mode programs |
409 | resend_too_soon | The same person was e-mailed less than 2 hours ago; Retry-After says when to try again |
409 | already_accepted, already_registered | There is no invitation to send: the partner joined, or the user registered |
409 | email_unavailable | The address belongs to another Advancer account |
409 | idempotency_key_in_use | A request with the same Idempotency-Key is still running; retry in a moment |
415 | unsupported_media_type | Send request bodies as application/json |
422 | validation_failed | The values are well formed but don't fit, e.g. a state of another subtopic |
422 | idempotency_key_reused | The Idempotency-Key was already used for a different request |
429 | rate_limited, quota_exceeded, invitation_limit_reached | Too many requests or invitations; wait for the seconds in Retry-After |
500 | internal_error | Unexpected error; quote error.traceId to support |