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.

Base URL: https://advancer.world/api/v1/customer
OpenAPI 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 for DELETE and resends). The API checks everything and answers with what would happen, without changing anything or sending anything.
  • Retries. POST calls accept an Idempotency-Key header: 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 an Idempotent-Replayed: true header, instead of repeating the operation. The same key with a different request gets 422 idempotency_key_reused. PUT and DELETE are 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 sent notify: false), skipped_recently_contacted, no_recipient, would_send (dry run) or none.
  • History. Every change made through the API is recorded as made by the API, with the key that made it.

Endpoints

GET /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 }
  }
}
GET /api/v1/customer/info
Get Customer Information

Returns information about your organization.

Response Fields
Field Type Description
organizationNamestringOrganization name
contactEmailstringAdministrator email
contactPhonestring?Phone number
streetAddressstringStreet address
postalCodestringZIP/Postal code
cityNamestringCity
countryNamestringCountry
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"
  }
}
GET /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
idintegerProgram identifier
titlestringProgram name
summarystring?Short description
createdDatedatetimeCreation date (UTC)
enabledbooleanActive status
modestringHow 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 }
}
GET /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
qstringSearch term, 1–100 characters (required)
limit, cursorSee Paging
Example Request
GET /api/v1/customer/programs/search?q=child
GET /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
idintegerUser identifier
fullNamestringUser's full name
emailAddressstringEmail address
phonestring?Phone number
registrationDatedatetime?Date of registration (UTC)
enabledbooleanActive status
jobTitlestring?Position/role
lastAccessDatedatetime?Last login (UTC)
isAdministratorbooleanCustomer admin flag
preferredLanguagestring?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 }
}
GET /api/v1/customer/users/search?q={query}
Search Users

Returns users whose name or email contains the search term (case-insensitive), paged like Get Users.

Query Parameters
Parameter Type Description
qstringSearch term, 1–100 characters (required)
limit, cursorSee Paging
Example Request
GET /api/v1/customer/users/search?q=john
PUT /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
emailstringCurrent email address of the user to update
Request Body (JSON)
Field Type Description
fullNamestring?New full name (max 255)
emailAddressstring?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.
phonestring?New phone number (max 20; an empty string clears it)
jobTitlestring?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"
  }
}
GET /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
programIdintegerThe program ID (from Get Programs endpoint)
Response Fields (per partner)
Field Type Description
idintegerPartner identifier
organizationNamestringPartner organization name
categorystringPartner type/category
contactEmailstringAdmin email
contactPhonestring?Phone number
streetAddressstringAddress
postalCodestringZIP/Postal code
cityNamestringCity
countryNamestringCountry
registrationDatedatetime?Registration date (UTC); null until the partner registers
enabledbooleanActive status
statusstringinvited until the partner registers, then registered
enrollmentobjectinvitedAt, 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.

EndpointReturns
GET /programs/{programId}The program, its stages, topics and subtopics (ids, names, order) and live counts
GET /programs/{programId}/structureThe states and transitions as ids, with the number of work items on each transition
GET /programs/{programId}/progressHow enrolled partners are spread over the stages, overall and per subtopic
GET /programs/{programId}/partners/progressPer partner: subtopics positioned, average and lowest stage, last activity (paged)
GET /programs/{programId}/partners/{partnerId}/progressA 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.

EndpointReturns
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
EndpointReturns
GET /kpisYour KPI definitions (paged)
GET /programs/{programId}/kpisPer KPI and state: partners reporting, average, minimum, maximum and standard deviation, or the share of yes for qualitative KPIs
GET /programs/{programId}/partners/{partnerId}/kpisThe partner's latest KPI values in the program
GET /programs/{programId}/awardsAward 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.

EndpointDoes
POST /programs/{programId}/enrollmentsEnrolls 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.

EndpointDoes
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
EndpointDoes
GET /users/{userId}One user of your organization, with pendingEmailAddress while a new address waits for confirmation.
POST /users/invitationsBody: 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.

GET /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.

ParameterDescription
since, untilThe period, in ISO 8601 (UTC). At most 90 days per request; default the last 7 days.
programId, partnerIdOnly this program or partner.
typesComma-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.

PUT /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.

PUT /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.

GET /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.

GET /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
200Success
400validation_failed, invalid_cursorThe request is not valid; see error.details
401unauthorizedMissing or invalid API credentials
404not_foundThe resource doesn't exist or belongs to another organization
405method_not_allowedThe HTTP method isn't supported for this resource
409program_mode_not_manualPositions can only be set in manual-mode programs
409resend_too_soonThe same person was e-mailed less than 2 hours ago; Retry-After says when to try again
409already_accepted, already_registeredThere is no invitation to send: the partner joined, or the user registered
409email_unavailableThe address belongs to another Advancer account
409idempotency_key_in_useA request with the same Idempotency-Key is still running; retry in a moment
415unsupported_media_typeSend request bodies as application/json
422validation_failedThe values are well formed but don't fit, e.g. a state of another subtopic
422idempotency_key_reusedThe Idempotency-Key was already used for a different request
429rate_limited, quota_exceeded, invitation_limit_reachedToo many requests or invitations; wait for the seconds in Retry-After
500internal_errorUnexpected error; quote error.traceId to support