PX OrderInfo
PX OrderInfo API product provides CenturyLink partners ability to retrieve the details and statuses of their orders.
This describes the Partner API specifications for partners wishing to configure CenturyLink available products, services and purchase on behalf of their customers. The new Px system enables partners to seamlessly and securely transact with CenturyLink electronically on cloud based next generation CRM platforms. The products supported as part of the current version of Partner APIs include Local Service packages, Long Distance packages, Broadband internet access and product bundles containing two or more products. The APIs also offer the ability to configure modems, services (e.g. broadband installation services), and accessories (for example CenturyLink @Ease).
OrderInfo API includes order status services for :
· New Orders
· Open Orders
· Order Details
Mass Market Partner APIs are available to new and existing partners who are selling local service packages, long-distance packages, broadband internet access, and product bundles to CenturyLink consumers and small business customers.
Mass Markets Partner APIs enable partners to seamlessly and securely qualify products and place orders with CenturyLink electronically on cloud-based next-generation CRM platforms. Digital information sharing between CenturyLink and our partners increases the speed and accuracy of products and services being delivered to the end customer.
1. Register a user.
2. Create sandbox and production apps under My Apps.
2. Obtain API keys. Upon approval, sandbox and production credentials will move to approved status. If you have questions about approvals use the Contact Us form.
3. Setup authorization. Using the navigation menu go to Code Samples for sample code for setting up authorization.
4. Make your first call. Using the navigation menu go to Documentation/Specification.
a. Click on the authorize button and add your credentials.
b. Select the POST/pxNewOrders API.
c. Click on the “Try it out” button.
d. Fill in the parameters and customize the sample code.
e. Click the execute button to see the response.
The below diagram depicts high level process flow for all partner APIs
Order Status
Partner will send the fields defined to return Order information. Px will then send the appropriate details in the response.
PX Order Status Flow outline to provide additional details and insight into the calls and how you should implement them.
NOTE: All order status calls should be performed during non-peak times or afterhours.
- New Orders
- newOrders call is used to pull in any order from the PX API, PX UI, and Phoned in orders
- You have the option to use any of the orderStatusSourceSystem (above in green), 2 or all 3 if you would like at a time. This allows you to trim down the responses by making calls specific to the order type. If you are only interested in phoned in orders you would send Phone in the orderStatusSourceSystem.
- Updates can be for a single day record up to 7 days of records in a single request
- For a single day request you would send
- fromDate as 10/10/2020
- toDate as 10/11/2020
- The toDate orders will not be included in the response
- For a multi-day request you would send
- fromDate as 10/10/2020
- toDate as 10/17/2020
- The toDate orders will not be included in the response
- For a single day request you would send
- Partners should implement this call as follows:
- Run a batch job every night using the partnerId to capture all orders for all of your sales codes
- If only interested in a specific sales code, then you can also send the request with the partnerId and a specific sales code
- Run a batch job every night using the partnerId to capture all orders for all of your sales codes
- From the “newOrders” response, absorb all partnerOrderId’s from the orderStatusSourceSystem(s) not already in partners DB
- If the new orders call was only for phoned in, then all likely should be absorbed.
- If the new orders call was only for UI order, likely all should be absorbed
- Any PX API orders issued should already be in partner DB from complete response (normal order flow) and not be needed at this point for absorption.
- As a result of having the response attribute orderStatusSourceSystem you will no longer code for the 1st 4 characters of the partnerorderid to identify a phoned in order
- Response attribute orderStatusSourceSystem for PX API would return the same partnerorderid you sent during the buy flow
- Response attribute orderStatusSourceSystem for PX UI would return partnerorderid that starts with a “U” followed by the order number
- Response attribute orderStatusSourceSystem for Phoned would return partnerorderid that starts with an “E” followed by the order number
- Records returned would include items like the partnerorderid, order number, address, account number, products, and order status
- newOrders call is used to pull in any order from the PX API, PX UI, and Phoned in orders
Once added to your system, these orders would follow the normal tracking process until they reach a terminal status
- Open Orders
- openOrders is used to obtain any order activity as well as those that have reached a “terminal” status in the past 7 days by a partnerId
- Run a batch job every night using your partnerId
- Search openOrders for any terminal status
- Terminal statuses are: Completed, Provider Cancelled, Tracking Terminated, Customer Cancelled, ATTTV and Declined
- If status is Provider Cancelled, Tracking Terminated, Customer Cancelled, or Declined, update the records accordingly and are now in a terminal status, no additional order status calls needed for those orders.
- All line items with the above would be updated in partner db to the associated ‘cancelled’ status.
- If status is Completed or ATTTV, update the records accordingly and are now in a terminal status,
- Do an order detail call for the partner order ID
- Update line items according to order detail response
- If status is Provider Cancelled, Tracking Terminated, Customer Cancelled, or Declined, update the records accordingly and are now in a terminal status, no additional order status calls needed for those orders.
Update account number, CTL order number, TN, etc from order detail response.
- Order Detail
- orderDetail is used to return order details for a single order record by using the sales code and the partnerorderid or the orderNumber
- If status is Completed, then run an orderDetail call
- Update line items from order detail call
- Update applicable fields as sometimes they can change
- Account number, order number, TN, products
- End, this is now a terminal order and will not change
- Records will retain the ‘terminal’ status, and be presented in the Open Order response for 7 calendar days (this is to account for minimal update of 1x per week)
Following Order Status values will be used to describe following states in process:
- RECEIVED means CTL has received the order
- PROVIDER IN PROCESS means valid order not yet terminal
- PROVIDER CANCELLED is cancelled by CTL or other Provider
- COMPLETED means service for product was installed
- OPEN means the order needs intervention from CTL
- PENDING means the order is being worked and requires information from customer
- DECLINED means the order will not be processed
- TRACKING TERMINATED means the system has lost track of the order and it has aged out
- PRE DECLINED means CTL has tried multiple times to reach the customer and have been unsuccessful and will not take further actions to reach the customer
- ATTTV means the order is a sale for ATT TV. This is a terminal status.
- PENDING DTV means the order is a sale awaiting DTV installation.
When setting up your Apps in My Apps you can create a Sandbox app and a Production app. You will then have two different sets of Consumer Keys and Consumer Secrets.
Base URL Sandbox: https://api-test.lumen.com/
Base URL Prod: https://api.lumen.com/
The Sandbox (test) environment is available to developers to build initial code against. It is a snapshot of production type data so that you can try out requests and responses. The Sandbox is not meant to be used as a QA environment. It is also not meant to duplicate production, therefore data that exists in Production may not be present in the Sandbox environment. Sandbox does not represent the up-time expectations of Production. We recommend that you complete shakeout testing against Production, keeping in mind that all transactions will be live.
Lumen supports the OAuth 2.0 client credentials authorization grant flow for external access by client-side applications. Once your credentials are approved you can go to Using OAuth 2.0 for detailed steps on getting a bearer token using basic authorization base64 encoding. Use the navigation menu and select Code Samples for an example of authorization.
PxAuthenticationService.java
----------------------------
package com.ctl.px.api.client;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.apache.oltu.oauth2.client.OAuthClient;
import org.apache.oltu.oauth2.client.URLConnectionClient;
import org.apache.oltu.oauth2.client.request.OAuthClientRequest;
import org.apache.oltu.oauth2.client.response.OAuthJSONAccessTokenResponse;
import org.apache.oltu.oauth2.common.OAuth;
import org.apache.oltu.oauth2.common.message.types.GrantType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Service
public class PxAuthenticationService {
Logger log = LoggerFactory.getLogger(PxAuthenticationService.class);
@Value("${px.sf.token.url}")
private String tokenURL;
@Value("${px.sf.token.basicAuth}")
private String basicAuth;
public String getAccessToken() {
String accessToken = null;
String methodName = new Object() {
}.getClass().getEnclosingMethod().getName();
try {
OAuthClient client = new OAuthClient(new URLConnectionClient());
OAuthClientRequest request = OAuthClientRequest.tokenLocation(tokenURL)
.setGrantType(GrantType.CLIENT_CREDENTIALS).buildBodyMessage();
request.addHeader(OAuth.HeaderType.AUTHORIZATION, "Basic " + basicAuth);
accessToken = client.accessToken(request, OAuthJSONAccessTokenResponse.class).getAccessToken();
} catch (Exception exn) {
exn.printStackTrace();
}
return accessToken;
}
}
PxNewOrderRestClient.java
------------------------
package com.ctl.px.api.client;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import com.ctl.px.api.model.NewOrderRequestObj;
@Component
public class PxNewOrderRestClient {
@Autowired
private PxAuthenticationService authenticationService;
@Autowired
private RestTemplateBuilder restTemplateBuilder;
@Value("${px.newOrder.url}")
private String newOrderUrl;
Logger log = LoggerFactory.getLogger(PxNewOrderRestClient.class);
public ResponseEntity<String> getNewOrder(NewOrderRequestObj newOrderRequest) {
RestTemplate restTemplate;
restTemplate = restTemplateBuilder.build();
String accessToken = authenticationService.getAccessToken();
log.debug("Using access token: " + accessToken);
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Bearer " + accessToken);
headers.setContentType(MediaType.APPLICATION_JSON);
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
ResponseEntity<String> response = null;
try {
HttpEntity<NewOrderRequestObj> request = new HttpEntity<>(newOrderRequest, headers);
response = restTemplate.postForEntity(newOrderUrl, request, String.class);
} catch (Exception e) {
log.debug("Exception occurred while making rest call to " + newOrderUrl + ", Exception was: "
+ e.getStackTrace());
}
return response;
}
}
PxOpenOrderRestClient.java
--------------------------
package com.ctl.px.api.client;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import com.ctl.px.api.model.OpenOrderRequestObj;
@Component
public class PxOpenOrderRestClient {
@Autowired
private PxAuthenticationService authenticationService;
@Autowired
private RestTemplateBuilder restTemplateBuilder;
@Value("${px.openOrder.url}")
private String openOrderUrl;
Logger log = LoggerFactory.getLogger(PxOpenOrderRestClient.class);
public ResponseEntity<String> getOpenOrders(OpenOrderRequestObj openOrderRequest) {
RestTemplate restTemplate;
restTemplate = restTemplateBuilder.build();
String accessToken = authenticationService.getAccessToken();
log.debug("Using access token: "+accessToken);
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization","Bearer "+accessToken);
headers.setContentType(MediaType.APPLICATION_JSON);
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
ResponseEntity<String> response = null;
try {
HttpEntity<OpenOrderRequestObj> request = new HttpEntity<>(openOrderRequest, headers);
response = restTemplate.postForEntity(openOrderUrl, request, String.class);
}catch(Exception e) {
log.debug("Exception occurred while making rest call to "+openOrderUrl+", Exception was: "+ e.getStackTrace());
}
return response;
}
}
PxOrderDetailClient.java
------------------------
package com.ctl.px.api.client;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import com.ctl.px.api.model.OrderDetailRequestObj;
@Component
public class PxOrderDetailClient {
@Autowired
private PxAuthenticationService authenticationService;
@Autowired
private RestTemplateBuilder restTemplateBuilder;
@Value("${px.orderDetail.url}")
private String orderDetailUrl;
Logger log = LoggerFactory.getLogger(PxOrderDetailClient.class);
public ResponseEntity<String> getOrderDetail(OrderDetailRequestObj orderDetailRequest) {
RestTemplate restTemplate;
restTemplate = restTemplateBuilder.build();
String accessToken = authenticationService.getAccessToken();
log.debug("Using access token: " + accessToken);
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Bearer " + accessToken);
headers.setContentType(MediaType.APPLICATION_JSON);
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
ResponseEntity<String> response = null;
try {
HttpEntity<OrderDetailRequestObj> request = new HttpEntity<>(orderDetailRequest, headers);
response = restTemplate.postForEntity(orderDetailUrl, request, String.class);
} catch (Exception e) {
log.debug("Exception occurred while making rest call to " + orderDetailUrl + ", Exception was: "
+ e.getStackTrace());
}
return response;
}
}
API Name | Reason | API Status Code | Internal Message Code | User Message |
openOrders | Invalid or missing partner id | 410 | 2245 | Invalid or missing Partner Id; TxId<> |
openOrders | Invalid or missing salescode | 410 | 2250 | Invalid or missing salescode; TxId<> |
orderDetail | Missing or Invalid PartnerOrderId | 410 | 2255 | Missing or Invalid PartnerOrderId; TxId<> |
orderDetail | Missing or Invalid salesCode | 410 | 2260 | Missing or Invalid salesCode; TxId<> |
orderDetail | Sales Code plus either Partner Order Id or Order# is required | 410 | 2285 | Sales Code plus either Partner Order Id or Order# is required; TxId<> |
orderDetail | No Order matching parameters | 410 | 2265 | No order matching parameters (Partner Order Id and Sales Code/Order#); TxId<> |
newOrders | Invalid salesCode provided | 401 | 2000 | Invalid salesCode provided; TxId<> |
newOrders | Missing or Invalid PartnerId | 401 | 2030 | Missing or Invalid PartnerId; TxId<> |
newOrders | Missing or Invalid Date | 401 | 2080 | Missing or Invalid To-Date and/or From-Date; TxId<> |
newOrders | Date Range Spans more than 7 days | 410 | 2090 | Date Range Spans more than 7 days (max can return 1 week); TxId<> |
newOrders | Missing or invalide orderStatusSourceSystem | 410 | 2295 | Missing or Invalid Order-Status Source System; TxId<> |
recapsDetail | No matching record within 90 days | 410 | 2230 | No matching record within 90 days; TxId<> |
recapsDetail | PartnerOrderId or OrderNumber must be provided | 410 | 2235 | PartnerOrderId or OrderNumber must be provided; TxId<> |
recapsDetail | SalesCode is missing or invalid | 410 | 2240 | SalesCode is missing or invalid; TxId<> |
Partners who would like to have API access please contact PXAPIAccessandSupport@lumen.com.
For API-specific support please complete the support form select the Help -> Contact Us menu option.